X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrsch%2Frg_sch_cmn.c;fp=src%2F5gnrsch%2Frg_sch_cmn.c;h=75fa54a270147233e376457eee36eabfba19d985;hb=3235ecfc7414aa0b72d0ad50db63ae8b5626045b;hp=0000000000000000000000000000000000000000;hpb=997e3f26d55352586a1d4d0c46c41a98452af88a;p=o-du%2Fl2.git diff --git a/src/5gnrsch/rg_sch_cmn.c b/src/5gnrsch/rg_sch_cmn.c new file mode 100755 index 000000000..75fa54a27 --- /dev/null +++ b/src/5gnrsch/rg_sch_cmn.c @@ -0,0 +1,32471 @@ +/******************************************************************************* +################################################################################ +# 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: LTE-MAC layer + + Type: C source file + + Desc: C source code for Entry point fucntions + + File: rg_sch_cmn.c + +**********************************************************************/ + +/** @file rg_sch_cmn.c +@brief This file implements the schedulers main access to MAC layer code. +*/ + +static const char* RLOG_MODULE_NAME="MAC"; +static int RLOG_FILE_ID=187; +static int RLOG_MODULE_ID=4096; + +/* header include files -- defines (.h) */ +#include "envopt.h" /* environment options */ +#include "envdep.h" /* environment dependent */ +#include "envind.h" /* environment independent */ +#include "gen.h" /* general layer */ +#include "ssi.h" /* system service interface */ +#include "cm_hash.h" /* common hash list */ +#include "cm_llist.h" /* common linked list library */ +#include "cm_err.h" /* common error */ +#include "cm_lte.h" /* common LTE */ +#include "cm5.h" +#include "lrg.h" +#include "rgr.h" +#include "tfu.h" +#include "rgm.h" +#include "rg_env.h" +#include "rg_sch_err.h" +#include "rg_sch_inf.h" +#include "rg_sch.h" +#include "rg_sch_cmn.h" +#include "rl_interface.h" +#include "rl_common.h" + +/* header/extern include files (.x) */ +#include "gen.x" /* general layer typedefs */ +#include "ssi.x" /* system services typedefs */ +#include "cm5.x" /* common timers */ +#include "cm_hash.x" /* common hash list */ +#include "cm_lib.x" /* common library */ +#include "cm_llist.x" /* common linked list */ +#include "cm_mblk.x" /* memory management */ +#include "cm_tkns.x" /* common tokens */ +#include "cm_lte.x" /* common tokens */ +#include "tfu.x" /* TFU types */ +#include "lrg.x" /* layer management typedefs for MAC */ +#include "rgr.x" /* layer management typedefs for MAC */ +#include "rgm.x" /* layer management typedefs for MAC */ +#include "rg_sch_inf.x" /* typedefs for Scheduler */ +#include "rg_sch.x" /* typedefs for Scheduler */ +#include "rg_sch_cmn.x" /* typedefs for Scheduler */ +#ifdef MAC_SCH_STATS +#include "lrg.x" /* Stats Structures */ +#endif /* MAC_SCH_STATS */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef EMTC_ENABLE +EXTERN U32 emtcStatsUlTomSrInd; +EXTERN U32 emtcStatsUlBsrTmrTxp; +#endif + +#define RG_ITBS_DIFF(_x, _y) ((_x) > (_y) ? (_x) - (_y) : (_y) - (_x)) +EXTERN Void rgSCHSc1UlInit ARGS((RgUlSchdApis *apis)); +#ifdef RG_PHASE2_SCHED +EXTERN Void rgSCHRrUlInit ARGS((RgUlSchdApis *apis)); +#ifdef EMTC_ENABLE +EXTERN Void rgSCHEmtcHqInfoFree ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP)); +EXTERN Void rgSCHEmtcRrUlInit ARGS((RgUlSchdApis *apis)); +EXTERN Void rgSCHEmtcCmnDlInit ARGS((Void)); +EXTERN Void rgSCHEmtcCmnUlInit ARGS((Void)); +EXTERN Void rgSCHEmtcCmnUeNbReset ARGS((RgSchUeCb *ueCb)); +EXTERN RgSchCmnCqiToTbs *rgSchEmtcCmnCqiToTbs[RGSCH_MAX_NUM_LYR_PERCW][RG_SCH_CMN_MAX_CP][RG_SCH_CMN_MAX_CFI]; +#endif +EXTERN Void rgSCHMaxciUlInit ARGS((RgUlSchdApis *apis)); +EXTERN Void rgSCHPfsUlInit ARGS((RgUlSchdApis *apis)); +#endif +EXTERN Void rgSCHSc1DlInit ARGS((RgDlSchdApis *apis)); +#ifdef RG_PHASE2_SCHED +EXTERN Void rgSCHRrDlInit ARGS((RgDlSchdApis *apis)); +#ifdef EMTC_ENABLE +EXTERN Void rgSCHEmtcRrDlInit ARGS((RgDlEmtcSchdApis *apis)); +#endif +EXTERN Void rgSCHMaxciDlInit ARGS((RgDlSchdApis *apis)); +EXTERN Void rgSCHPfsDlInit ARGS((RgDlSchdApis *apis)); +#ifdef TFU_UPGRADE +EXTERN Void rgSCHDlfsInit ARGS((RgDlfsSchdApis *apis)); +#endif +#endif +#ifdef EMTC_ENABLE +EXTERN Void rgSCHCmnGetCqiEmtcDciFrmt2AggrLvl ARGS((RgSchCellCb *cell)); +EXTERN Void rgSCHCmnGetEmtcDciFrmtSizes ARGS((RgSchCellCb *cell)); +EXTERN Void rgSCHEmtcRrUlProcRmvFrmRetx ARGS((RgSchCellCb *cell, RgSchUlHqProcCb *proc)); +EXTERN S16 rgSCHCmnPrecompEmtcMsg3Vars +ARGS(( +RgSchCmnUlCell *cellUl, +U8 ccchCqi, +U16 msgSzA, +U8 sbSize, +Bool isEcp +)); +PUBLIC Void rgSCHEmtcCmnUeCcchSduDel +( +RgSchCellCb *cell, +RgSchUeCb *ueCb +); +EXTERN Void rgSCHEmtcRmvFrmTaLst +( +RgSchCmnDlCell *cellDl, +RgSchUeCb *ue +); +EXTERN Void rgSCHEmtcInitTaLst +( +RgSchCmnDlCell *cellDl +); +EXTERN Void rgSCHEmtcAddToTaLst +( +RgSchCmnDlCell *cellDl, +RgSchUeCb *ue +); + +#endif + +#ifdef RGR_SI_SCH +PRIVATE Void rgSCHDlSiSched ARGS((RgSchCellCb *cell, + RgSchCmnDlRbAllocInfo *allocInfo, + RgInfSfAlloc *subfrmAlloc)); +PRIVATE Void rgSCHChkNUpdSiCfg ARGS((RgSchCellCb *cell)); +PRIVATE Void rgSCHSelectSi ARGS((RgSchCellCb *cell)); +#endif /*RGR_SI_SCH*/ +/* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD +PRIVATE S16 rgSCHCmnNonDlfsUpdDSFRTyp2Alloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +); +PRIVATE S16 rgSCHCmnBuildRntpInfo ( +RgSchCellCb *cell, +U8 *rntpPtr, +U8 startRb, +U8 nmbRb, +U16 bw +); +#endif + +PUBLIC Void rgSCHCmnDlSpsSch +( + RgSchCellCb *cell +); +/* LTE_ADV_FLAG_REMOVED_END */ + +PRIVATE Void rgSCHCmnNonDlfsBcchPcchRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHBcchPcchDlRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnDlBcchPcchAlloc ARGS(( +RgSchCellCb *cell +)); +#ifdef RGR_CQI_REPT +PRIVATE Void rgSCHCmnDlCqiOnPucchInd ARGS (( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + RgrUeCqiRept *ueCqiRept, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + )); +PRIVATE Void rgSCHCmnDlCqiOnPuschInd ARGS (( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPusch *puschCqi, + RgrUeCqiRept *ueCqiRept, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + )); +#else +PRIVATE Void rgSCHCmnDlCqiOnPucchInd ARGS (( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + )); +PRIVATE Void rgSCHCmnDlCqiOnPuschInd ARGS (( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPusch *puschCqi + )); +#endif +/* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT +PRIVATE S16 rgSCHCmnUeDlPwrCtColltCqiRept ARGS(( + RgSchCellCb *cell, + RgSchUeCb *ue, + RgrUeCqiRept *ueCqiRept)); +#endif /* End of RGR_CQI_REPT */ +/* Fix: syed align multiple UEs to refresh at same time */ +PRIVATE Void rgSCHCmnGetRefreshPer ARGS(( + RgSchCellCb *cell, + RgSchUeCb *ue, + U32 *waitPer)); +PRIVATE S16 rgSCHCmnApplyUeRefresh ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue)); +#ifdef DL_LA +PUBLIC Void rgSCHCmnDlSetUeAllocLmtLa ARGS +(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE Void rgSCHCheckAndSetTxScheme ARGS +(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +#endif + +#ifdef LTE_TDD +PRIVATE U32 rgSCHCmnCalcDwPtsTbSz ARGS +(( +RgSchCellCb *cell, +U32 bo, +U8 *rb, +U8 *iTbs, +U8 lyr, +U8 cfi +)); + +PRIVATE Void rgSCHCmnCalcDwPtsTbSz2Cw ARGS +(( +RgSchCellCb *cell, +U32 bo, +U8 *rb, +U8 maxRb, +U8 *iTbs1, +U8 *iTbs2, +U8 lyr1, +U8 lyr2, +U32 *tb1Sz, +U32 *tb2Sz, +U8 cfi +)); + +#endif +PRIVATE Void rgSCHCmnNonDlfsType0Alloc +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +RgSchUeCb *ue +); +PRIVATE Void rgSCHCmnInitRbAlloc ARGS +(( +RgSchCellCb *cell +)); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/* local defines */ +PUBLIC RgSchdApis rgSchCmnApis; +PRIVATE RgUlSchdApis rgSchUlSchdTbl[RGSCH_NUM_SCHEDULERS]; +PRIVATE RgDlSchdApis rgSchDlSchdTbl[RGSCH_NUM_SCHEDULERS]; +#ifdef EMTC_ENABLE +PRIVATE RgUlSchdApis rgSchEmtcUlSchdTbl[RGSCH_NUM_EMTC_SCHEDULERS]; +PRIVATE RgDlEmtcSchdApis rgSchEmtcDlSchdTbl[RGSCH_NUM_EMTC_SCHEDULERS]; +#endif +#ifdef RG_PHASE2_SCHED +PRIVATE RgDlfsSchdApis rgSchDlfsSchdTbl[RGSCH_NUM_DLFS_SCHEDULERS]; +#endif +PRIVATE RgUlSchdInits rgSchUlSchdInits = RGSCH_ULSCHED_INITS; +PRIVATE RgDlSchdInits rgSchDlSchdInits = RGSCH_DLSCHED_INITS; +#ifdef EMTC_ENABLE +PRIVATE RgEmtcUlSchdInits rgSchEmtcUlSchdInits = RGSCH_EMTC_ULSCHED_INITS; +PRIVATE RgEmtcDlSchdInits rgSchEmtcDlSchdInits = RGSCH_EMTC_DLSCHED_INITS; +#endif +#if (defined (RG_PHASE2_SCHED) && defined (TFU_UPGRADE)) +PRIVATE RgDlfsSchdInits rgSchDlfsSchdInits = RGSCH_DLFSSCHED_INITS; +#endif + +typedef Void (*RgSchCmnDlAllocRbFunc) ARGS((RgSchCellCb *cell, RgSchDlSf *subFrm, +RgSchUeCb *ue, U32 bo, U32 *effBo, RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo)); +typedef U8 (*RgSchCmnDlGetPrecInfFunc) ARGS((RgSchCellCb *cell, RgSchUeCb *ue, + U8 numLyrs, Bool bothCwEnbld)); + +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1 ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +)); +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1A ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +)); +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1B ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +)); +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2 ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +)); +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2A ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +)); +PRIVATE Void rgSCHCmnDlAllocTxRbTM1 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocTxRbTM2 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocTxRbTM3 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocTxRbTM4 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +#ifdef RG_UNUSED +PRIVATE Void rgSCHCmnDlAllocTxRbTM5 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +#endif +PRIVATE Void rgSCHCmnDlAllocTxRbTM6 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocTxRbTM7 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocRetxRbTM1 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocRetxRbTM2 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocRetxRbTM3 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocRetxRbTM4 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +#ifdef RG_UNUSED +PRIVATE Void rgSCHCmnDlAllocRetxRbTM5 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +#endif +PRIVATE Void rgSCHCmnDlAllocRetxRbTM6 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlAllocRetxRbTM7 ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); + +#ifdef LTE_ADV +PRIVATE U8 rgSchGetN1ResCount ARGS (( + RgSchUeCb *ue, + U16 servCellId +)); +PUBLIC Bool rgSchCmnChkDataOnlyOnPcell +( + RgSchUeCb *ue, + RgSchDlSf *dlSf +); +#endif /*LTE_ADV */ +PUBLIC U8 rgSCHCmnCalcPcqiBitSz +( + RgSchUeCb *ueCb, + U8 numTxAnt +); + +#ifndef LTE_ADV +/* Functions specific to each transmission mode for DL Tx RB Allocation*/ +RgSchCmnDlAllocRbFunc dlAllocTxRbFunc[7] = {rgSCHCmnDlAllocTxRbTM1, +rgSCHCmnDlAllocTxRbTM2, rgSCHCmnDlAllocTxRbTM3, rgSCHCmnDlAllocTxRbTM4, +NULLP, rgSCHCmnDlAllocTxRbTM6, rgSCHCmnDlAllocTxRbTM7}; + +/* Functions specific to each transmission mode for DL Retx RB Allocation*/ +RgSchCmnDlAllocRbFunc dlAllocRetxRbFunc[7] = {rgSCHCmnDlAllocRetxRbTM1, +rgSCHCmnDlAllocRetxRbTM2, rgSCHCmnDlAllocRetxRbTM3, rgSCHCmnDlAllocRetxRbTM4, +NULLP, rgSCHCmnDlAllocRetxRbTM6, rgSCHCmnDlAllocRetxRbTM7}; +#else +/* Functions specific to each transmission mode for DL Tx RB Allocation*/ +RgSchCmnDlAllocRbFunc dlAllocTxRbFunc[9] = {rgSCHCmnDlAllocTxRbTM1, +rgSCHCmnDlAllocTxRbTM2, rgSCHCmnDlAllocTxRbTM3, rgSCHCmnDlAllocTxRbTM4, +NULLP, rgSCHCmnDlAllocTxRbTM6, rgSCHCmnDlAllocTxRbTM7, NULLP, NULLP}; + +/* Functions specific to each transmission mode for DL Retx RB Allocation*/ +RgSchCmnDlAllocRbFunc dlAllocRetxRbFunc[9] = {rgSCHCmnDlAllocRetxRbTM1, +rgSCHCmnDlAllocRetxRbTM2, rgSCHCmnDlAllocRetxRbTM3, rgSCHCmnDlAllocRetxRbTM4, +NULLP, rgSCHCmnDlAllocRetxRbTM6, rgSCHCmnDlAllocRetxRbTM7, NULLP, NULLP}; + +#endif + + +PRIVATE U8 rgSCHCmnDlTM3PrecInf2 ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +)); +PRIVATE U8 rgSCHCmnDlTM3PrecInf4 ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +)); +PRIVATE U8 rgSCHCmnDlTM4PrecInf2 ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +)); +PRIVATE U8 rgSCHCmnDlTM4PrecInf4 ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +)); +/* Functions specific to each transmission mode for DL RB Allocation*/ +RgSchCmnDlGetPrecInfFunc getPrecInfoFunc[2][2] = { +{rgSCHCmnDlTM3PrecInf2, rgSCHCmnDlTM3PrecInf4}, +{rgSCHCmnDlTM4PrecInf2, rgSCHCmnDlTM4PrecInf4} +}; + +PRIVATE S16 rgSCHCmnDlAlloc1CwRetxRb ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *tbInfo, +U8 noLyr, +U8 *numRb, +U32 *effBo +)); +PRIVATE S16 rgSCHCmnDlAlloc2CwRetxRb ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U8 *numRb, +Bool *swpFlg, +U32 *effBo +)); +PRIVATE Void rgSCHCmnDlTM3TxTx ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlTM3TxRetx ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); +PRIVATE Void rgSCHCmnDlTM3RetxRetx ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +)); + +PRIVATE Void rgSCHCmnNonDlfsUpdTyp2Alloc ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +)); +/* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD +PRIVATE Void rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +)); +#endif +/* LTE_ADV_FLAG_REMOVED_END */ +PRIVATE Void rgSCHCmnDlRbInfoAddUeTx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc +)); +PRIVATE Void rgSCHCmnDlRbInfoAddUeRetx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +)); +PRIVATE Void rgSCHCmnDlAdd2NonSchdRetxLst ARGS(( +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc +)); +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRetxRb ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *reTxTb, +RgSchDlHqTbCb *txTb, +U8 *numRb, +U32 *effBo +)); +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRb ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U32 bo, +U8 *numRb, +U32 *effBo +)); +PRIVATE S16 rgSCHCmnDlAlloc1CwTxRb ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *tbInfo, +U32 bo, +U8 *numRb, +U32 *effBo +)); +#ifndef LTEMAC_SPS +PRIVATE Void rgSCHCmnFillHqPTb ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +U8 tbAllocIdx, +RgSchPdcch *pdcch +)); +#endif +#ifdef LTEMAC_SPS +PRIVATE Void rgSCHCmnDlGetBestFitHole ARGS(( +U32 *allocMask, +U8 numMaskRbs, +U32 *crntAllocMask, +U8 rbsReq, +U8 *allocStart, +U8 *allocNumRbs, +Bool isPartialAlloc +)); +#ifdef RGSCH_SPS_UNUSED +PRIVATE U32 rgSCHCmnGetRaType1Mask ARGS(( +U8 rbIdx, +U8 rbgSize, +U8 *type1Subset +)); +#endif +PRIVATE U32 rgSCHCmnGetRaType0Mask ARGS(( +U8 rbIdx, +U8 rbgSize +)); +PRIVATE U32 rgSCHCmnGetRaType2Mask ARGS(( +U8 rbIdx, +U8 *maskIdx +)); +#endif + +PUBLIC Bool rgSCHCmnRetxAllocAvoid ARGS(( +RgSchDlSf *subFrm, +RgSchCellCb *cell, +RgSchDlHqProcCb *proc +)); + +PUBLIC U16 rgSCHCmnGetSiSetId ARGS(( +U16 sfn, +U8 sf, +U16 minPeriodicity +)); + +#ifdef TFU_UPGRADE +PRIVATE S16 rgSCHCmnUlMdfyGrntForCqi ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 maxRb, +U32 *numSb, +U8 *iTbs, +U32 hqSz, +U32 stepDownItbs, +U32 effTgt +)); +#endif + +#ifdef RG_5GTF +//TODO_SID: Currenly table is only for 100 Prbs. Need to modify wrt VRBG table 8.1.5.2.1-1 V5G_213 +U32 rgSch5gtfTbSzTbl[MAX_5GTF_MCS] = + {1864, 5256, 8776, 13176, 17576, 21976, 26376, 31656, 35176, 39576, 43976, 47496, 52776, 59376, 66392}; +U32 g5gtfTtiCnt = 0; +U32 gUl5gtfSrRecv = 0; +U32 gUl5gtfBsrRecv = 0; +U32 gUl5gtfUeSchPick = 0; +U32 gUl5gtfPdcchSchd = 0; +U32 gUl5gtfAllocAllocated = 0; +U32 gUl5gtfUeRbAllocDone = 0; +U32 gUl5gtfUeRmvFnlzZeroBo = 0; +U32 gUl5gtfUeFnlzReAdd = 0; +U32 gUl5gtfPdcchSend = 0; +U32 gUl5gtfRbAllocFail = 0; +U32 ul5gtfsidUlMarkUl = 0; +U32 ul5gtfsidDlSchdPass = 0; +U32 ul5gtfsidDlAlreadyMarkUl = 0; +U32 ul5gtfTotSchdCnt = 0; +#endif + +/* CQI Offset Index to Beta CQI Offset value mapping, + * stored as parts per 1000. Reserved is set to 0. + * Refer 36.213 sec 8.6.3 Tbl 8.6.3-3 */ +PUBLIC U32 rgSchCmnBetaCqiOffstTbl[16] = {0, 0, 1125, + 1250, 1375, 1625, 1750, 2000, 2250, 2500, 2875, + 3125, 3500, 4000, 5000, 6250}; +PUBLIC U32 rgSchCmnBetaHqOffstTbl[16] = {2000, 2500, 3125, + 4000, 5000, 6250, 8000,10000, 12625, 15875, 20000, + 31000, 50000,80000,126000,0}; +PUBLIC U32 rgSchCmnBetaRiOffstTbl[16] = {1250, 1625, 2000, + 2500, 3125, 4000, 5000, 6250, 8000, 10000,12625, + 15875,20000,0,0,0}; +PUBLIC S8 rgSchCmnDlCqiDiffOfst[8] = {0, 1, 2, 3, -4, -3, -2, -1}; + +/* Include CRS REs while calculating Efficiency */ +CONSTANT PRIVATE U8 rgSchCmnAntIdx[5] = {0,0,1,0,2}; +CONSTANT PRIVATE U8 rgSchCmnNumResForCrs[5] = {0,6,12,0,16}; +U32 cfiSwitchCnt ; +U32 cfiIncr ; +U32 cfiDecr ; + + +#ifdef TFU_UPGRADE +PUBLIC S8 rgSchCmnApUeSelDiffCqi[4] = {1, 2, 3, 4}; +PUBLIC S8 rgSchCmnApEnbConfDiffCqi[4] = {0, 1, 2, -1}; +#endif + +typedef struct rgSchCmnDlUeDciFrmtOptns +{ + TfuDciFormat spfcDciFrmt; /* TM(Transmission Mode) specific DCI format. + * Search space : UE Specific by C-RNTI only. */ + U8 spfcDciRAType; /* Resource Alloctn(RA) type for spfcDciFrmt */ + TfuDciFormat prfrdDciFrmt; /* Preferred DCI format among the available + * options for TD (Transmit Diversity) */ + U8 prfrdDciRAType; /* Resource Alloctn(RA) type for prfrdDciFrmt */ +}RgSchCmnDlUeDciFrmtOptns; +#ifndef LTE_ADV + +/* DCI Format options for each Transmission Mode */ +RgSchCmnDlUeDciFrmtOptns rgSchCmnDciFrmtOptns[7] = { + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_2A,RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_2, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1D,RG_SCH_CMN_RA_TYPE2, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1B,RG_SCH_CMN_RA_TYPE2, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2} +}; + +#else +/* DCI Format options for each Transmission Mode */ +RgSchCmnDlUeDciFrmtOptns rgSchCmnDciFrmtOptns[9] = { + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_2A,RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_2, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1D,RG_SCH_CMN_RA_TYPE2, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1B,RG_SCH_CMN_RA_TYPE2, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2}, + {TFU_DCI_FORMAT_1, RG_SCH_CMN_RA_TYPE0, TFU_DCI_FORMAT_1A, RG_SCH_CMN_RA_TYPE2} +}; +#endif + + +typedef struct rgSchCmnDlImcsTbl +{ + U8 modOdr; /* Modulation Order */ + U8 iTbs; /* ITBS */ +}RgSchCmnDlImcsTbl[29]; + +CONSTANT struct rgSchCmnMult235Info +{ + U8 match; /* Closest number satisfying 2^a.3^b.5^c, with a bias + * towards the smaller number */ + U8 prvMatch; /* Closest number not greater than array index + * satisfying 2^a.3^b.5^c */ +} rgSchCmnMult235Tbl[110+1] = { + {0, 0}, /* dummy */ + {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}, {6, 6}, {8, 8}, + {9, 9}, {10, 10}, {10, 10}, {12, 12}, {12, 12}, {15, 12}, {15, 15}, + {16, 16}, {16, 16}, {18, 18}, {18, 18}, {20, 20}, {20, 20}, {20, 20}, + {24, 20}, {24, 24}, {25, 25}, {25, 25}, {27, 27}, {27, 27}, {30, 27}, + {30, 30}, {30, 30}, {32, 32}, {32, 32}, {32, 32}, {36, 32}, {36, 36}, + {36, 36}, {36, 36}, {40, 36}, {40, 40}, {40, 40}, {40, 40}, {45, 40}, + {45, 40}, {45, 45}, {45, 45}, {48, 45}, {48, 48}, {48, 48}, {50, 50}, + {50, 50}, {50, 50}, {54, 50}, {54, 54}, {54, 54}, {54, 54}, {54, 54}, + {60, 54}, {60, 54}, {60, 60}, {60, 60}, {60, 60}, {64, 60}, {64, 64}, + {64, 64}, {64, 64}, {64, 64}, {64, 64}, {72, 64}, {72, 64}, {72, 64}, + {72, 72}, {72, 72}, {75, 72}, {75, 75}, {75, 75}, {75, 75}, {80, 75}, + {80, 75}, {80, 80}, {81, 81}, {81, 81}, {81, 81}, {81, 81}, {81, 81}, + {90, 81}, {90, 81}, {90, 81}, {90, 81}, {90, 90}, {90, 90}, {90, 90}, + {90, 90}, {96, 90}, {96, 90}, {96, 96}, {96, 96}, {96, 96}, {100, 96}, + {100, 100}, {100, 100}, {100, 100}, {100, 100}, {100, 100}, {108, 100}, + {108, 100}, {108, 100}, {108, 108}, {108, 108}, {108, 108} +}; + +/* R8 Upgrade */ +/* BI table from 36.321 Table 7.2.1 */ +CONSTANT PRIVATE S16 rgSchCmnBiTbl[RG_SCH_CMN_NUM_BI_VAL] = { + 0, 10, 20, 30,40,60,80,120,160,240,320,480,960}; +PUBLIC RgSchCmnUlCqiInfo rgSchCmnUlCqiTbl[RG_SCH_CMN_UL_NUM_CQI] = { + { 0, 0 }, + {RGSCH_CMN_QM_CQI_1,RGSCH_CMN_UL_EFF_CQI_1 }, + {RGSCH_CMN_QM_CQI_2,RGSCH_CMN_UL_EFF_CQI_2 }, + {RGSCH_CMN_QM_CQI_3,RGSCH_CMN_UL_EFF_CQI_3 }, + {RGSCH_CMN_QM_CQI_4,RGSCH_CMN_UL_EFF_CQI_4 }, + {RGSCH_CMN_QM_CQI_5,RGSCH_CMN_UL_EFF_CQI_5 }, + {RGSCH_CMN_QM_CQI_6,RGSCH_CMN_UL_EFF_CQI_6 }, + {RGSCH_CMN_QM_CQI_7,RGSCH_CMN_UL_EFF_CQI_7 }, + {RGSCH_CMN_QM_CQI_8,RGSCH_CMN_UL_EFF_CQI_8 }, + {RGSCH_CMN_QM_CQI_9,RGSCH_CMN_UL_EFF_CQI_9 }, + {RGSCH_CMN_QM_CQI_10,RGSCH_CMN_UL_EFF_CQI_10 }, + {RGSCH_CMN_QM_CQI_11,RGSCH_CMN_UL_EFF_CQI_11 }, + {RGSCH_CMN_QM_CQI_12,RGSCH_CMN_UL_EFF_CQI_12 }, + {RGSCH_CMN_QM_CQI_13,RGSCH_CMN_UL_EFF_CQI_13 }, + {RGSCH_CMN_QM_CQI_14,RGSCH_CMN_UL_EFF_CQI_14 }, + {RGSCH_CMN_QM_CQI_15,RGSCH_CMN_UL_EFF_CQI_15 }, +}; + +#ifdef RG_UNUSED +/* This table maps a (delta_offset * 2 + 2) to a (beta * 8) + * where beta is 10^-(delta_offset/10) rounded off to nearest 1/8 + */ +PRIVATE U16 rgSchCmnUlBeta8Tbl[29] = { + 6, RG_SCH_CMN_UL_INVALID_BETA8, 8, 9, 10, 11, 13, 14, 16, 18, 20, 23, + 25, 28, 32, RG_SCH_CMN_UL_INVALID_BETA8, 40, RG_SCH_CMN_UL_INVALID_BETA8, + 50, RG_SCH_CMN_UL_INVALID_BETA8, 64, RG_SCH_CMN_UL_INVALID_BETA8, 80, + RG_SCH_CMN_UL_INVALID_BETA8, 101, RG_SCH_CMN_UL_INVALID_BETA8, 127, + RG_SCH_CMN_UL_INVALID_BETA8, 160 +}; +#endif + +/* QCI to SVC priority mapping. Index specifies the Qci*/ +PRIVATE U8 rgSchCmnDlQciPrio[RG_SCH_CMN_MAX_QCI] = RG_SCH_CMN_QCI_TO_PRIO; + +/* The configuration is efficiency measured per 1024 REs. */ +/* The first element stands for when CQI is not known */ +/* This table is used to translate CQI to its corrospoding */ +/* allocation parameters. These are currently from 36.213 */ +/* Just this talbe needs to be edited for modifying the */ +/* the resource allocation behaviour */ + +/* ADD CQI to MCS mapping correction + * single dimensional array is replaced by 2 dimensions for different CFI*/ +PRIVATE U16 rgSchCmnCqiPdschEff[4][16] = {RG_SCH_CMN_CQI_TO_PDSCH_EFF_CFI0 ,RG_SCH_CMN_CQI_TO_PDSCH_EFF_CFI1, + RG_SCH_CMN_CQI_TO_PDSCH_EFF_CFI2,RG_SCH_CMN_CQI_TO_PDSCH_EFF_CFI3}; + +PRIVATE U16 rgSchCmn2LyrCqiPdschEff[4][16] = {RG_SCH_CMN_2LYR_CQI_TO_PDSCH_EFF_CFI0 ,RG_SCH_CMN_2LYR_CQI_TO_PDSCH_EFF_CFI1, + RG_SCH_CMN_2LYR_CQI_TO_PDSCH_EFF_CFI2, RG_SCH_CMN_2LYR_CQI_TO_PDSCH_EFF_CFI3}; + +/* This configuration determines the transalation of a UEs CQI to its */ +/* PDCCH coding efficiency. This may be edited based on the installation */ +PRIVATE U8 rgSchCmnDlRvTbl[4] = {0, 2, 3, 1}; /* RVIdx sequence is corrected*/ + +/* Indexed by [DciFrmt]. + * Considering the following definition in determining the dciFrmt index. + * typedef enum +{ + TFU_DCI_FORMAT_0, + TFU_DCI_FORMAT_1, + TFU_DCI_FORMAT_1A, + TFU_DCI_FORMAT_1B, + TFU_DCI_FORMAT_1C, + TFU_DCI_FORMAT_1D, + TFU_DCI_FORMAT_2, + TFU_DCI_FORMAT_2A, + TFU_DCI_FORMAT_3, + TFU_DCI_FORMAT_3A +} TfuDciFormat; +*/ +PRIVATE U16 rgSchCmnDciFrmtSizes[10]; + + +PRIVATE U16 rgSchCmnCqiPdcchEff[16] = RG_SCH_CMN_CQI_TO_PDCCH_EFF; + +#ifdef LTE_TDD + +PUBLIC RgSchTddUlDlSubfrmTbl rgSchTddUlDlSubfrmTbl = { + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME}, + {RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME, RG_SCH_TDD_SPL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_UL_SUBFRAME, RG_SCH_TDD_DL_SUBFRAME} +}; + +/* SPS_INTG_FIX */ +#ifdef LTEMAC_SPS +PUBLIC U8 rgSchTddSpsDlMaxRetxTbl[RGSCH_MAX_TDD_UL_DL_CFG] = { + /* 0 */ 6, + /* 1 */ 7, + /* 2 */ 8, + /* 3 */ 11, + /* 4 */ 12, + /* 5 */ 13, + /* 6 */ 7}; + +#endif + + +/* Special Subframes in OFDM symbols */ +/* ccpu00134197-MOD-Correct the number of symbols */ +PUBLIC RgSchTddSplSubfrmInfoTbl rgSchTddSplSubfrmInfoTbl = { + {3, 1, 1, 3, 1, 1}, + {9, 1, 1, 8, 1, 1}, + {10, 1, 1, 9, 1, 1}, + {11, 1, 1, 10, 1, 1}, + {12, 1, 1, 3, 2, 2}, + {3, 2, 2, 8, 2, 2}, + {9, 2, 2, 9, 2, 2}, + {10, 2, 2, 0, 0, 0}, + {11, 2, 2, 0, 0, 0} +}; + +/* PHICH 'm' value Table */ +PUBLIC RgSchTddPhichMValTbl rgSchTddPhichMValTbl = { + {2, 1, 0, 0, 0, 2, 1, 0, 0, 0}, + {0, 1, 0, 0, 1, 0, 1, 0, 0, 1}, + {0, 0, 0, 1, 0, 0, 0, 0, 1, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {1, 1, 0, 0, 0, 1, 1, 0, 0, 1} +}; + +/* PHICH 'K' value Table */ +PUBLIC RgSchTddKPhichTbl rgSchTddKPhichTbl = { + {0, 0, 4, 7, 6, 0, 0, 4, 7, 6}, + {0, 0, 4, 6, 0, 0, 0, 4, 6, 0}, + {0, 0, 6, 0, 0, 0, 0, 6, 0, 0}, + {0, 0, 6, 6, 6, 0, 0, 0, 0, 0}, + {0, 0, 6, 6, 0, 0, 0, 0, 0, 0}, + {0, 0, 6, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 4, 6, 6, 0, 0, 4, 7, 0} +}; + +/* Uplink association index 'K' value Table */ +PUBLIC RgSchTddUlAscIdxKDashTbl rgSchTddUlAscIdxKDashTbl = { + {0, 0, 6, 4, 0, 0, 0, 6, 4, 0}, + {0, 0, 4, 0, 0, 0, 0, 4, 0, 0}, + {0, 0, 4, 4, 4, 0, 0, 0, 0, 0}, + {0, 0, 4, 4, 0, 0, 0, 0, 0, 0}, + {0, 0, 4, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 7, 7, 5, 0, 0, 7, 7, 0} +}; + + +/* PUSCH 'K' value Table */ +PUBLIC RgSchTddPuschTxKTbl rgSchTddPuschTxKTbl = { + {4, 6, 0, 0, 0, 4, 6, 0, 0, 0}, + {0, 6, 0, 0, 4, 0, 6, 0, 0, 4}, + {0, 0, 0, 4, 0, 0, 0, 0, 4, 0}, + {4, 0, 0, 0, 0, 0, 0, 0, 4, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 4, 4}, + {0, 0, 0, 0, 0, 0, 0, 0, 4, 0}, + {7, 7, 0, 0, 0, 7, 7, 0, 0, 5} +}; + +/* PDSCH to PUCCH Table for DL Harq Feed back. Based on the + Downlink association set index 'K' table */ +PUBLIC U8 rgSchTddPucchTxTbl[7][10] = { + {4, 6, 0, 0, 0, 4, 6, 0, 0, 0}, + {7, 6, 0, 0, 4, 7, 6, 0, 0, 4}, + {7, 6, 0, 4, 8, 7, 6, 0, 4, 8}, + {4, 11, 0, 0, 0, 7, 6, 6, 5, 5}, + {12, 11, 0, 0, 8, 7, 7, 6, 5, 4}, + {12, 11, 0, 9, 8, 7, 6, 5, 4, 13}, + {7, 7, 0, 0, 0, 7, 7, 0, 0, 5} +}; + +/* Table to fetch the next DL sf idx for applying the + new CFI. The next Dl sf Idx at which the new CFI + is applied is always the starting Sf of the next ACK/NACK + Fdbk bundle. + + Ex: In Cfg-2, sf4 and sf9 are the only subframes at which + a new ACK/NACK bundle of DL subframes can start + + D S U D D D S U D D D S U D D D S U D D + 4 9 + + dlSf Array for Cfg-2: + sfNum: 0 1 3 4 5 6 8 9 0 1 3 4 5 6 8 9 + sfIdx: 0 1 2 3 4 5 6 7 8 9 10 11 12 12 14 15 + + If CFI changes at sf0, nearest DL SF bundle >= 4 TTI is sf4 + So at sf4 the new CFI can be applied. To arrive at sf4 from + sf0, the sfIdx has to be increased by 3 */ + +PUBLIC U8 rgSchTddPdcchSfIncTbl[7][10] = { + /* A/N Bundl: 0,1,5,6*/ {2, 1, 0, 0, 0, 2, 1, 0, 0, 0}, + /* A/N Bundl: 0,4,5,9*/ {2, 2, 0, 0, 3, 2, 2, 0, 0, 3}, + /* A/N Bundl: 4,9*/ {3, 6, 0, 5, 4, 3, 6, 0, 5, 4}, + /* A/N Bundl: 1,7,9*/ {4, 3, 0, 0, 0, 4, 5, 4, 6, 5}, + /* A/N Bundl: 0,6*/ {4, 3, 0, 0, 6, 5, 4, 7, 6, 5}, + /* A/N Bundl: 9*/ {8, 7, 0, 6, 5, 4, 12, 11, 10, 9}, + /* A/N Bundl: 0,1,5,6,9*/ {2, 1, 0, 0, 0, 2, 2, 0, 0, 3} +}; + + +/* combine compilation fixes */ +#ifdef LTEMAC_SPS +/* subframe offset values to be used when twoIntervalsConfig is enabled in UL + * SPS for a UE */ +PUBLIC RgSchTddSfOffTbl rgSchTddSfOffTbl = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, -1, 0, 0, 0, 1, -1, 0}, + {0, 0, 5, 0, 0, 0, 0, -5, 0, 0}, + {0, 0, 1, 1, -2, 0, 0, 0, 0, 0}, + {0, 0, 1, -1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + + +/* Table to determine when uplink SPS configured grants should + * explicitly be reserved in a subframe. When enries are same + * as that of Msg3SubfrmTbl, indicates competition with msg3. + * As of now, this is same as Msg3SubfrmTbl (leaving out uldlcfg 2), + * except that all 255s are now zeros. */ +PUBLIC RgSchTddSpsUlRsrvTbl rgSchTddSpsUlRsrvTbl = { + {0, 0, 0, 6, 8, 0, 0, 0, 6, 8}, + {0, 0, 6, 9, 0, 0, 0, 6, 9, 0}, + {0, 0, 10, 0, 0, 0, 0, 10, 0, 0}, + {0, 0, 0, 0, 8, 0, 7, 7, 14, 0}, + {0, 0, 0, 9, 0, 0, 7, 15, 0, 0}, + {0, 0, 10, 0, 0, 0, 16, 0, 0, 0}, + {0, 0, 0, 0, 8, 0, 0, 0, 9, 0} +}; + +/* Inverse DL Assoc Set index Table */ +PUBLIC RgSchTddInvDlAscSetIdxTbl rgSchTddInvDlAscSetIdxTbl = { + {4, 6, 0, 0, 0, 4, 6, 0, 0, 0}, + {7, 6, 0, 0, 4, 7, 6, 0, 0, 4}, + {7, 6, 0, 4, 8, 7, 6, 0, 4, 8}, + {4, 11, 0, 0, 0, 7, 6, 6, 5, 5}, + {12, 11, 0, 0, 8, 7, 7, 6, 5, 4}, + {12, 11, 0, 9, 8, 7, 6, 5, 4, 13}, + {7, 7, 0, 0, 0, 7, 7, 0, 0, 5} +}; + +#endif /* (LTEMAC_SPS ) */ + +/* Number of Uplink subframes Table */ +PRIVATE U8 rgSchTddNumUlSf[] = {6, 4, 2, 3, 2, 1, 5}; + +/* Downlink HARQ processes Table */ +PUBLIC RgSchTddUlNumHarqProcTbl rgSchTddUlNumHarqProcTbl = { 7, 4, 2, 3, 2, 1, 6}; + +/* Uplink HARQ processes Table */ +PUBLIC RgSchTddDlNumHarqProcTbl rgSchTddDlNumHarqProcTbl = { 4, 7, 10, 9, 12, 15, 6}; + +/* Downlink association index set 'K' value Table */ +PUBLIC RgSchTddDlAscSetIdxKTbl rgSchTddDlAscSetIdxKTbl = { + { {0, {0}}, {0, {0}}, {1, {6}}, {0, {0}}, {1, {4}}, {0, {0}}, {0, {0}}, {1, {6}}, {0, {0}}, {1, {4}} }, + + { {0, {0}}, {0, {0}}, {2, {7, 6}}, {1, {4}}, {0, {0}}, {0, {0}}, {0, {0}}, {2, {7, 6}}, {1, {4}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {4, {8, 7, 4, 6}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {4, {8, 7, 4, 6}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {3, {7, 6, 11}}, {2, {6, 5}}, {2, {5, 4}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {4, {12, 8, 7, 11}}, {4, {6, 5, 4, 7}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {9, {13, 12, 9, 8, 7, 5, 4, 11, 6}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {1, {7}}, {1, {7}}, {1, {5}}, {0, {0}}, {0, {0}}, {1, {7}}, {1, {7}}, {0, {0}} } +}; + + /* ccpu132282-ADD-the table rgSchTddDlAscSetIdxKTbl is rearranged in + * decreasing order of Km, this is used to calculate the NCE used for + * calculating N1Pucch Resource for Harq*/ +PUBLIC RgSchTddDlAscSetIdxKTbl rgSchTddDlHqPucchResCalTbl = { + { {0, {0}}, {0, {0}}, {1, {6}}, {0, {0}}, {1, {4}}, {0, {0}}, {0, {0}}, {1, {6}}, {0, {0}}, {1, {4}} }, + + { {0, {0}}, {0, {0}}, {2, {7, 6}}, {1, {4}}, {0, {0}}, {0, {0}}, {0, {0}}, {2, {7, 6}}, {1, {4}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {4, {8, 7, 6, 4}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {4, {8, 7, 6, 4}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {3, {11, 7, 6}}, {2, {6, 5}}, {2, {5, 4}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {4, {12, 11, 8, 7}}, {4, {7, 6, 5, 4}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {9, {13, 12, 11, 9, 8, 7, 6, 5, 4}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}} }, + + { {0, {0}}, {0, {0}}, {1, {7}}, {1, {7}}, {1, {5}}, {0, {0}}, {0, {0}}, {1, {7}}, {1, {7}}, {0, {0}} } +}; + +/* Minimum number of Ack/Nack feeback information to be + stored for each UL-DL configuration */ +PUBLIC RgSchTddANFdbkMapTbl rgSchTddANFdbkMapTbl = {4, 4, 2, 3, 2, 1, 5}; + +/* Uplink switch points and number of UL subframes Table */ +PUBLIC RgSchTddMaxUlSubfrmTbl rgSchTddMaxUlSubfrmTbl = { + {2,3,3}, {2,2,2}, {2,1,1}, {1,3,0}, {1,2,0}, {1,1,0}, {2,3,2} +}; + +/* Uplink switch points and number of DL subframes Table */ +PUBLIC RgSchTddMaxDlSubfrmTbl rgSchTddMaxDlSubfrmTbl = { + {2,2,2}, {2,3,3}, {2,4,4}, {1,7,0}, {1,8,0}, {1,9,0}, {2,2,3} +}; + +/* Number of UL subframes present before a particular subframe */ +PUBLIC RgSchTddNumUlSubfrmTbl rgSchTddNumUlSubfrmTbl = { + {0, 0, 1, 2, 3, 3, 3, 4, 5, 6}, + {0, 0, 1, 2, 2, 2, 2, 3, 4, 4}, + {0, 0, 1, 1, 1, 1, 1, 2, 2, 2}, + {0, 0, 1, 2, 3, 3, 3, 3, 3, 3}, + {0, 0, 1, 2, 2, 2, 2, 2, 2, 2}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 0, 1, 2, 3, 3, 3, 4, 5, 5} +}; + +/* Number of DL subframes present till a particular subframe */ +PUBLIC RgSchTddNumDlSubfrmTbl rgSchTddNumDlSubfrmTbl = { + {1, 2, 2, 2, 2, 3, 4, 4, 4, 4}, + {1, 2, 2, 2, 3, 4, 5, 5, 5, 6}, + {1, 2, 2, 3, 4, 5, 6, 6, 7, 8}, + {1, 2, 2, 2, 2, 3, 4, 5, 6, 7}, + {1, 2, 2, 2, 3, 4, 5, 6, 7, 8}, + {1, 2, 2, 3, 4, 5, 6, 7, 8, 9}, + {1, 2, 2, 2, 2, 3, 4, 4, 4, 5} +}; + + +/* Nearest possible UL subframe Index from UL subframe + * DL Index < UL Index */ +PUBLIC RgSchTddLowDlSubfrmIdxTbl rgSchTddLowDlSubfrmIdxTbl = { + {0, 1, 1, 1, 1, 5, 6, 6, 6, 6}, + {0, 1, 1, 1, 4, 5, 6, 6, 6, 9}, + {0, 1, 1, 3, 4, 5, 6, 6, 8, 9}, + {0, 1, 1, 1, 1, 5, 6, 7, 8, 9}, + {0, 1, 1, 1, 4, 5, 6, 7, 8, 9}, + {0, 1, 1, 3, 4, 5, 6, 7, 8, 9}, + {0, 1, 1, 1, 1, 5, 6, 6, 6, 9} +}; + +/* Nearest possible DL subframe Index from UL subframe + * DL Index > UL Index + * 10 represents Next SFN low DL Idx */ +PUBLIC RgSchTddHighDlSubfrmIdxTbl rgSchTddHighDlSubfrmIdxTbl = { + {0, 1, 5, 5, 5, 5, 6, 10, 10, 10}, + {0, 1, 4, 4, 4, 5, 6, 9, 9, 9}, + {0, 1, 3, 3, 4, 5, 6, 8, 8, 9}, + {0, 1, 5, 5, 5, 5, 6, 7, 8, 9}, + {0, 1, 4, 4, 4, 5, 6, 7, 8, 9}, + {0, 1, 3, 3, 4, 5, 6, 7, 8, 9}, + {0, 1, 5, 5, 5, 5, 6, 9, 9, 9} +}; + +/* RACH Message3 related information */ +PUBLIC RgSchTddMsg3SubfrmTbl rgSchTddMsg3SubfrmTbl = { + {7, 6, 255, 255, 255, 7, 6, 255, 255, 255}, + {7, 6, 255, 255, 8, 7, 6, 255, 255, 8}, + {7, 6, 255, 9, 8, 7, 6, 255, 9, 8}, + {12, 11, 255, 255, 255, 7, 6, 6, 6, 13}, + {12, 11, 255, 255, 8, 7, 6, 6, 14, 13}, + {12, 11, 255, 9, 8, 7, 6, 15, 14, 13}, + {7, 6, 255, 255, 255, 7, 6, 255, 255, 8} +}; + +/* ccpu00132341-DEL Removed rgSchTddRlsDlSubfrmTbl and used Kset table for + * releasing DL HARQs */ + +/* DwPTS Scheduling Changes Start */ +/* Provides the number of Cell Reference Signals in DwPTS + * region per RB */ +PRIVATE U8 rgSchCmnDwptsCrs[2][3] = {/* [Spl Sf cfg][Ant Port] */ + {4, 8, 16}, /* Spl Sf cfg 1,2,3,6,7,8 */ + {6, 12, 20}, /* Spl Sf cfg 4 */ +}; + +PRIVATE S8 rgSchCmnSplSfDeltaItbs[9] = RG_SCH_DWPTS_ITBS_ADJ; +/* DwPTS Scheduling Changes End */ +#endif + + +PRIVATE U32 rgSchCmnBsrTbl[64] = { + 0, 10, 12, 14, 17, 19, 22, 26, + 31, 36, 42, 49, 57, 67, 78, 91, + 107, 125, 146, 171, 200, 234, 274, 321, + 376, 440, 515, 603, 706, 826, 967, 1132, + 1326, 1552, 1817, 2127, 2490, 2915, 3413, 3995, + 4677, 5476, 6411, 7505, 8787, 10287, 12043, 14099, + 16507, 19325, 22624, 26487, 31009, 36304, 42502, 49759, + 58255, 68201, 79846, 93479, 109439, 128125, 150000, 220000 +}; + +PRIVATE U32 rgSchCmnExtBsrTbl[64] = { + 0, 10, 13, 16, 19, 23, 29, 35, + 43, 53, 65, 80, 98, 120, 147, 181, + 223, 274, 337, 414, 509, 625, 769, 945, + 1162, 1429, 1757, 2161, 2657, 3267, 4017, 4940, + 6074, 7469, 9185, 11294, 13888, 17077, 20999, 25822, + 31752, 39045, 48012, 59039, 72598, 89272, 109774, 134986, + 165989, 204111, 250990, 308634, 379519, 466683, 573866, 705666, + 867737, 1067031, 1312097, 1613447, 1984009, 2439678, 3000000, 3100000 +}; + + +PRIVATE U8 rgSchCmnUlRvIdxToIMcsTbl[4] = {32, 30, 31, 29}; + +PUBLIC U8 rgSchCmnUlCqiToTbsTbl[RG_SCH_CMN_MAX_CP][RG_SCH_CMN_UL_NUM_CQI]; + +PUBLIC RgSchTbSzTbl rgTbSzTbl = { + { + {16, 32, 56, 88, 120, 152, 176, 208, 224, 256, 288, 328, 344, 376, 392, 424, 456, 488, 504, 536, 568, 600, 616, 648, 680, 712, 744, 776, 776, 808, 840, 872, 904, 936, 968, 1000, 1032, 1032, 1064, 1096, 1128, 1160, 1192, 1224, 1256, 1256, 1288, 1320, 1352, 1384, 1416, 1416, 1480, 1480, 1544, 1544, 1608, 1608, 1608, 1672, 1672, 1736, 1736, 1800, 1800, 1800, 1864, 1864, 1928, 1928, 1992, 1992, 2024, 2088, 2088, 2088, 2152, 2152, 2216, 2216, 2280, 2280, 2280, 2344, 2344, 2408, 2408, 2472, 2472, 2536, 2536, 2536, 2600, 2600, 2664, 2664, 2728, 2728, 2728, 2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 2984, 2984, 3112}, + {24, 56, 88, 144, 176, 208, 224, 256, 328, 344, 376, 424, 456, 488, 520, 568, 600, 632, 680, 712, 744, 776, 808, 872, 904, 936, 968, 1000, 1032, 1064, 1128, 1160, 1192, 1224, 1256, 1288, 1352, 1384, 1416, 1416, 1480, 1544, 1544, 1608, 1608, 1672, 1736, 1736, 1800, 1800, 1864, 1864, 1928, 1992, 1992, 2024, 2088, 2088, 2152, 2152, 2216, 2280, 2280, 2344, 2344, 2408, 2472, 2472, 2536, 2536, 2600, 2600, 2664, 2728, 2728, 2792, 2792, 2856, 2856, 2856, 2984, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3240, 3368, 3368, 3368, 3496, 3496, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008}, + {32, 72, 144, 176, 208, 256, 296, 328, 376, 424, 472, 520, 568, 616, 648, 696, 744, 776, 840, 872, 936, 968, 1000, 1064, 1096, 1160, 1192, 1256, 1288, 1320, 1384, 1416, 1480, 1544, 1544, 1608, 1672, 1672, 1736, 1800, 1800, 1864, 1928, 1992, 2024, 2088, 2088, 2152, 2216, 2216, 2280, 2344, 2344, 2408, 2472, 2536, 2536, 2600, 2664, 2664, 2728, 2792, 2856, 2856, 2856, 2984, 2984, 3112, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3368, 3496, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 3880, 4008, 4008, 4008, 4136, 4136, 4136, 4264, 4264, 4264, 4392, 4392, 4392, 4584, 4584, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968}, + {40, 104, 176, 208, 256, 328, 392, 440, 504, 568, 616, 680, 744, 808, 872, 904, 968, 1032, 1096, 1160, 1224, 1256, 1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2536, 2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4392, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5352, 5352, 5544, 5544, 5544, 5736, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6200, 6456, 6456}, + {56, 120, 208, 256, 328, 408, 488, 552, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1192, 1288, 1352, 1416, 1480, 1544, 1608, 1736, 1800, 1864, 1928, 1992, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2600, 2664, 2728, 2792, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, 4776, 4968, 4968, 4968, 5160, 5160, 5160, 5352, 5352, 5544, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992}, + {72, 144, 224, 328, 424, 504, 600, 680, 776, 872, 968, 1032, 1128, 1224, 1320, 1384, 1480, 1544, 1672, 1736, 1864, 1928, 2024, 2088, 2216, 2280, 2344, 2472, 2536, 2664, 2728, 2792, 2856, 2984, 3112, 3112, 3240, 3368, 3496, 3496, 3624, 3752, 3752, 3880, 4008, 4008, 4136, 4264, 4392, 4392, 4584, 4584, 4776, 4776, 4776, 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9528}, + {328, 176, 256, 392, 504, 600, 712, 808, 936, 1032, 1128, 1224, 1352, 1480, 1544, 1672, 1736, 1864, 1992, 2088, 2216, 2280, 2408, 2472, 2600, 2728, 2792, 2984, 2984, 3112, 3240, 3368, 3496, 3496, 3624, 3752, 3880, 4008, 4136, 4136, 4264, 4392, 4584, 4584, 4776, 4776, 4968, 4968, 5160, 5160, 5352, 5352, 5544, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6456, 6456, 6456, 6712, 6712, 6968, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10296, 10296, 10680, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448}, + {104, 224, 328, 472, 584, 712, 840, 968, 1096, 1224, 1320, 1480, 1608, 1672, 1800, 1928, 2088, 2216, 2344, 2472, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3368, 3496, 3624, 3752, 3880, 4008, 4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, 5544, 5736, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11448, 11832, 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 12960, 13536, 13536}, + {120, 256, 392, 536, 680, 808, 968, 1096, 1256, 1384, 1544, 1672, 1800, 1928, 2088, 2216, 2344, 2536, 2664, 2792, 2984, 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 8248, 8504, 8504, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11832, 11832, 12216, 12216, 12216, 12576, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15264}, + {136, 296, 456, 616, 776, 936, 1096, 1256, 1416, 1544, 1736, 1864, 2024, 2216, 2344, 2536, 2664, 2856, 2984, 3112, 3368, 3496, 3624, 3752, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, 5160, 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8248, 8504, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10296, 10296, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11832, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16416, 16992, 16992, 16992, 16992, 17568}, + {144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, 2088, 2280, 2472, 2664, 2792, 2984, 3112, 3368, 3496, 3752, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8504, 8504, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10296, 10680, 10680, 11064, 11064, 11448, 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080}, + {176, 376, 584, 776, 1000, 1192, 1384, 1608, 1800, 2024, 2216, 2408, 2600, 2792, 2984, 3240, 3496, 3624, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 5992, 6200, 6456, 6712, 6968, 6968, 7224, 7480, 7736, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11064, 11448, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080, 19848, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152, 22152, 22152}, + {208, 440, 680, 904, 1128, 1352, 1608, 1800, 2024, 2280, 2472, 2728, 2984, 3240, 3368, 3624, 3880, 4136, 4392, 4584, 4776, 4968, 5352, 5544, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 8760, 9144, 9528, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11064, 11448, 11832, 11832, 12216, 12216, 12576, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 23688, 24496, 24496, 24496, 24496, 25456}, + {224, 488, 744, 1000, 1256, 1544, 1800, 2024, 2280, 2536, 2856, 3112, 3368, 3624, 3880, 4136, 4392, 4584, 4968, 5160, 5352, 5736, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9144, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11448, 11448, 11832, 12216, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 26416, 26416, 26416, 26416, 27376, 27376, 27376, 27376, 28336, 28336}, + {256, 552, 840, 1128, 1416, 1736, 1992, 2280, 2600, 2856, 3112, 3496, 3752, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 5992, 6200, 6456, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912, 9912, 10296, 10680, 11064, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704}, + {280, 600, 904, 1224, 1544, 1800, 2152, 2472, 2728, 3112, 3368, 3624, 4008, 4264, 4584, 4968, 5160, 5544, 5736, 6200, 6456, 6712, 6968, 7224, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912, 10296, 10296, 10680, 11064, 11448, 11832, 11832, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008}, + {328, 632, 968, 1288, 1608, 1928, 2280, 2600, 2984, 3240, 3624, 3880, 4264, 4584, 4968, 5160, 5544, 5992, 6200, 6456, 6712, 7224, 7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 9912, 10296, 10680, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 21384, 21384, 22152, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 34008, 35160, 35160, 35160, 35160}, + {336, 696, 1064, 1416, 1800, 2152, 2536, 2856, 3240, 3624, 4008, 4392, 4776, 5160, 5352, 5736, 6200, 6456, 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10296, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 26416, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 35160, 36696, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 39232}, + {376, 776, 1160, 1544, 1992, 2344, 2792, 3112, 3624, 4008, 4392, 4776, 5160, 5544, 5992, 6200, 6712, 7224, 7480, 7992, 8248, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 14112, 14112, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816}, + {408, 840, 1288, 1736, 2152, 2600, 2984, 3496, 3880, 4264, 4776, 5160, 5544, 5992, 6456, 6968, 7224, 7736, 8248, 8504, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 15264, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19080, 19848, 20616, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888}, + {440, 904, 1384, 1864, 2344, 2792, 3240, 3752, 4136, 4584, 5160, 5544, 5992, 6456, 6968, 7480, 7992, 8248, 8760, 9144, 9912, 10296, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 14688, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 20616, 21384, 22152, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 48936, 51024, 51024, 51024}, + {488, 1000, 1480, 1992, 2472, 2984, 3496, 4008, 4584, 4968, 5544, 5992, 6456, 6968, 7480, 7992, 8504, 9144, 9528, 9912, 10680, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 15840, 16416, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056}, + {520, 1064, 1608, 2152, 2664, 3240, 3752, 4264, 4776, 5352, 5992, 6456, 6968, 7480, 7992, 8504, 9144, 9528, 10296, 10680, 11448, 11832, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 16992, 17568, 18336, 19080, 19080, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256}, + {552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, 6968, 7480, 7992, 8504, 9144, 9912, 10296, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 19848, 20616, 21384, 22152, 22152, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776}, + {584, 1192, 1800, 2408, 2984, 3624, 4264, 4968, 5544, 5992, 6712, 7224, 7992, 8504, 9144, 9912, 10296, 11064, 11448, 12216, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 19848, 20616, 21384, 22152, 22920, 22920, 23688, 24496, 25456, 25456, 26416, 26416, 27376, 28336, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592}, + {616, 1256, 1864, 2536, 3112, 3752, 4392, 5160, 5736, 6200, 6968, 7480, 8248, 8760, 9528, 10296, 10680, 11448, 12216, 12576, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 20616, 21384, 22152, 22920, 23688, 24496, 24496, 25456, 26416, 26416, 27376, 28336, 28336, 29296, 29296, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 66592, 68808, 68808, 68808, 71112}, + {712, 1480, 2216, 2984, 3752, 4392, 5160, 5992, 6712, 7480, 8248, 8760, 9528, 10296, 11064, 11832, 12576, 13536, 14112, 14688, 15264, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 25456, 26416, 27376, 28336, 29296, 29296, 30576, 30576, 31704, 32856, 32856, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376, 75376} + }, + { + {32, 88, 152, 208, 256, 328, 376, 424, 488, 536, 600, 648, 712, 776, 808, 872, 936, 1000, 1032, 1096, 1160, 1224, 1256, 1320, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1800, 1864, 1928, 1992, 2088, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2536, 2600, 2664, 2728, 2792, 2856, 2856, 2984, 2984, 3112, 3112, 3240, 3240, 3240, 3368, 3368, 3496, 3496, 3624, 3624, 3624, 3752, 3752, 3880, 3880, 4008, 4008, 4008, 4136, 4136, 4136, 4264, 4264, 4392, 4392, 4584, 4584, 4584, 4776, 4776, 4776, 4776, 4968, 4968, 5160, 5160, 5160, 5160, 5160, 5352, 5352, 5544, 5544, 5544, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 5992, 5992, 6200}, + {56, 144, 208, 256, 344, 424, 488, 568, 632, 712, 776, 872, 936, 1000, 1064, 1160, 1224, 1288, 1384, 1416, 1544, 1608, 1672, 1736, 1800, 1864, 1992, 2024, 2088, 2152, 2280, 2344, 2408, 2472, 2536, 2600, 2728, 2792, 2856, 2856, 2984, 3112, 3112, 3240, 3240, 3368, 3496, 3496, 3624, 3624, 3752, 3752, 3880, 4008, 4008, 4008, 4136, 4136, 4264, 4264, 4392, 4584, 4584, 4776, 4776, 4776, 4968, 4968, 5160, 5160, 5160, 5160, 5352, 5544, 5544, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 7992}, + {72, 176, 256, 328, 424, 520, 616, 696, 776, 872, 968, 1064, 1160, 1256, 1320, 1416, 1544, 1608, 1672, 1800, 1864, 1992, 2088, 2152, 2216, 2344, 2408, 2536, 2600, 2664, 2792, 2856, 2984, 3112, 3112, 3240, 3368, 3368, 3496, 3624, 3624, 3752, 3880, 4008, 4008, 4136, 4264, 4264, 4392, 4584, 4584, 4584, 4776, 4776, 4968, 5160, 5160, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5736, 5992, 5992, 6200, 6200, 6200, 6456, 6456, 6456, 6712, 6712, 6712, 6968, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7736, 7736, 7736, 7992, 7992, 7992, 8248, 8248, 8248, 8504, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9912, 9912}, + {104, 208, 328, 440, 568, 680, 808, 904, 1032, 1160, 1256, 1384, 1480, 1608, 1736, 1864, 1992, 2088, 2216, 2344, 2472, 2536, 2664, 2792, 2856, 2984, 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4136, 4264, 4392, 4392, 4584, 4776, 4776, 4968, 4968, 5160, 5352, 5352, 5544, 5544, 5736, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6712, 6968, 6968, 7224, 7224, 7224, 7480, 7480, 7736, 7736, 7992, 7992, 8248, 8248, 8504, 8504, 8760, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10296, 10680, 10680, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11448, 11832, 11832, 11832, 11832, 12576, 12576, 12576, 12576, 12960, 12960}, + {120, 256, 408, 552, 696, 840, 1000, 1128, 1288, 1416, 1544, 1736, 1864, 1992, 2152, 2280, 2408, 2600, 2728, 2856, 2984, 3112, 3240, 3496, 3624, 3752, 3880, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 4968, 5160, 5352, 5544, 5544, 5736, 5992, 5992, 6200, 6200, 6456, 6456, 6712, 6968, 6968, 7224, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8248, 8504, 8504, 8760, 8760, 9144, 9144, 9144, 9528, 9528, 9912, 9912, 9912, 10296, 10296, 10296, 10680, 10680, 11064, 11064, 11064, 11448, 11448, 11448, 11832, 11832, 11832, 11832, 12576, 12576, 12576, 12960, 12960, 12960, 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840}, + {144, 328, 504, 680, 872, 1032, 1224, 1384, 1544, 1736, 1928, 2088, 2280, 2472, 2664, 2792, 2984, 3112, 3368, 3496, 3752, 3880, 4008, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5736, 5992, 6200, 6200, 6456, 6712, 6968, 6968, 7224, 7480, 7480, 7736, 7992, 7992, 8248, 8504, 8760, 8760, 9144, 9144, 9528, 9528, 9528, 9912, 9912, 10296, 10296, 10680, 10680, 11064, 11064, 11448, 11448, 11448, 11832, 11832, 11832, 12576, 12576, 12576, 12960, 12960, 13536, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080, 19080}, + {176, 392, 600, 808, 1032, 1224, 1480, 1672, 1864, 2088, 2280, 2472, 2728, 2984, 3112, 3368, 3496, 3752, 4008, 4136, 4392, 4584, 4776, 4968, 5160, 5352, 5736, 5992, 5992, 6200, 6456, 6712, 6968, 6968, 7224, 7480, 7736, 7992, 8248, 8248, 8504, 8760, 9144, 9144, 9528, 9528, 9912, 9912, 10296, 10296, 10680, 10680, 11064, 11448, 11448, 11832, 11832, 11832, 12576, 12576, 12960, 12960, 12960, 13536, 13536, 14112, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 16416, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 18336, 19080, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 20616, 21384, 21384, 21384, 21384, 24264, 24264, 24264, 22920, 22920, 22920}, + {224, 472, 712, 968, 1224, 1480, 1672, 1928, 2216, 2472, 2664, 2984, 3240, 3368, 3624, 3880, 4136, 4392, 4584, 4968, 5160, 5352, 5736, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9144, 9528, 9912, 9912, 10296, 10680, 10680, 11064, 11448, 11448, 11832, 11832, 12216, 12576, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 14688, 14688, 15264, 15264, 15840, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 21384, 24264, 24264, 24264, 22920, 22920, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 25456, 25456, 25456, 27376, 27376}, + {256, 536, 808, 1096, 1384, 1672, 1928, 2216, 2536, 2792, 3112, 3368, 3624, 3880, 4264, 4584, 4776, 4968, 5352, 5544, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8504, 8760, 9144, 9144, 9528, 9912, 9912, 10296, 10680, 11064, 11064, 11448, 11832, 12216, 12216, 12576, 12960, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15264, 15264, 15840, 15840, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19080, 19848, 19848, 19848, 20616, 20616, 21384, 21384, 21384, 24264, 24264, 24264, 22920, 22920, 22920, 23688, 23688, 24496, 24496, 24496, 25456, 25456, 25456, 25456, 25456, 25456, 27376, 27376, 27376, 27376, 28336, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 30576}, + {296, 616, 936, 1256, 1544, 1864, 2216, 2536, 2856, 3112, 3496, 3752, 4136, 4392, 4776, 5160, 5352, 5736, 5992, 6200, 6712, 6968, 7224, 7480, 7992, 8248, 8504, 8760, 9144, 9528, 9912, 10296, 10296, 10680, 11064, 11448, 11832, 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14112, 14688, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 16992, 17568, 17568, 18336, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 20616, 21384, 21384, 24264, 24264, 24264, 22920, 22920, 23688, 23688, 23688, 24496, 24496, 25456, 25456, 25456, 25456, 25456, 27376, 27376, 27376, 27376, 28336, 28336, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 32856, 34008, 34008, 34008, 34008, 35160}, + {328, 680, 1032, 1384, 1736, 2088, 2472, 2792, 3112, 3496, 3880, 4264, 4584, 4968, 5352, 5736, 5992, 6200, 6712, 6968, 7480, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11448, 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15264, 15840, 16416, 16416, 16992, 16992, 17568, 18336, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 20616, 21384, 21384, 24264, 24264, 22920, 22920, 22920, 23688, 23688, 24496, 24496, 25456, 25456, 25456, 25456, 25456, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 36696, 36696, 37888, 37888, 37888, 37888}, + {376, 776, 1192, 1608, 2024, 2408, 2792, 3240, 3624, 4008, 4392, 4776, 5352, 5736, 5992, 6456, 6968, 7224, 7736, 7992, 8504, 8760, 9144, 9528, 9912, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 13536, 14112, 14688, 14688, 15264, 15840, 16416, 16416, 16992, 17568, 17568, 18336, 18336, 19080, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22152, 22920, 22920, 23688, 23688, 24496, 24496, 25456, 25456, 25456, 25456, 27376, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 29296, 30576, 30576, 31704, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 36696, 37888, 37888, 37888, 37888, 39232, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816, 43816}, + {440, 904, 1352, 1800, 2280, 2728, 3240, 3624, 4136, 4584, 4968, 5544, 5992, 6456, 6712, 7224, 7736, 8248, 8760, 9144, 9528, 9912, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15264, 15840, 16416, 16992, 17568, 17568, 18336, 19080, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22152, 22920, 23688, 23688, 24496, 24496, 25456, 25456, 25456, 25456, 27376, 27376, 28336, 28336, 28336, 29296, 29296, 30576, 30576, 30576, 31704, 31704, 32856, 32856, 32856, 34008, 34008, 35160, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 46888, 48936, 48936, 48936, 48936, 51024}, + {488, 1000, 1544, 2024, 2536, 3112, 3624, 4136, 4584, 5160, 5736, 6200, 6712, 7224, 7736, 8248, 8760, 9144, 9912, 10296, 10680, 11448, 11832, 12216, 12960, 13536, 14112, 14688, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 18336, 19080, 19848, 19848, 20616, 21384, 21384, 22152, 22920, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 26416, 27376, 27376, 28336, 29296, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 52752, 55056, 55056, 55056, 55056, 57336, 57336}, + {552, 1128, 1736, 2280, 2856, 3496, 4008, 4584, 5160, 5736, 6200, 6968, 7480, 7992, 8504, 9144, 9912, 10296, 11064, 11448, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 19848, 20616, 21384, 22152, 22152, 22920, 23688, 24496, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 45352, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776}, + {600, 1224, 1800, 2472, 3112, 3624, 4264, 4968, 5544, 6200, 6712, 7224, 7992, 8504, 9144, 9912, 10296, 11064, 11832, 12216, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 20616, 21384, 22152, 22920, 23688, 23688, 24496, 25456, 25456, 26416, 27376, 27376, 28336, 29296, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 46888, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808}, + {632, 1288, 1928, 2600, 3240, 3880, 4584, 5160, 5992, 6456, 7224, 7736, 8504, 9144, 9912, 10296, 11064, 11832, 12216, 12960, 13536, 14112, 14688, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 24496, 25456, 26416, 26416, 27376, 28336, 28336, 29296, 30576, 30576, 31704, 31704, 32856, 32856, 34008, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 39232, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 68808, 71112, 71112, 71112, 71112}, + {696, 1416, 2152, 2856, 3624, 4392, 5160, 5736, 6456, 7224, 7992, 8760, 9528, 10296, 10680, 11448, 12216, 12960, 13536, 14688, 15264, 15840, 16416, 17568, 18336, 19080, 19848, 20616, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 26416, 27376, 28336, 29296, 29296, 30576, 30576, 31704, 32856, 32856, 34008, 35160, 35160, 36696, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 71112, 73712, 73712, 73712, 73712, 76208, 76208, 76208, 78704, 78704, 78704, 78704}, + {776, 1544, 2344, 3112, 4008, 4776, 5544, 6200, 7224, 7992, 8760, 9528, 10296, 11064, 11832, 12576, 13536, 14112, 15264, 15840, 16416, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 27376, 27376, 28336, 29296, 30576, 30576, 31704, 32856, 32856, 34008, 35160, 35160, 36696, 37888, 37888, 39232, 39232, 40576, 40576, 42368, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936}, + {840, 1736, 2600, 3496, 4264, 5160, 5992, 6968, 7736, 8504, 9528, 10296, 11064, 12216, 12960, 13536, 14688, 15264, 16416, 16992, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 24496, 25456, 25456, 26416, 27376, 28336, 29296, 30576, 30576, 31704, 32856, 34008, 34008, 35160, 36696, 36696, 37888, 39232, 39232, 40576, 40576, 42368, 43816, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 51024, 51024, 51024, 52752, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 61664, 63776, 63776, 66592, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176, 81176, 84760, 84760, 84760, 87936, 87936, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 93800}, + {904, 1864, 2792, 3752, 4584, 5544, 6456, 7480, 8248, 9144, 10296, 11064, 12216, 12960, 14112, 14688, 15840, 16992, 17568, 18336, 19848, 20616, 21384, 22152, 22920, 24496, 25456, 26416, 27376, 28336, 29296, 29296, 30576, 31704, 32856, 34008, 34008, 35160, 36696, 36696, 37888, 39232, 40576, 40576, 42368, 42368, 43816, 45352, 45352, 46888, 46888, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 59256, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176, 84760, 84760, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 93800, 97896, 97896, 97896, 97896, 97896, 101840, 101840, 101840}, + {1000, 1992, 2984, 4008, 4968, 5992, 6968, 7992, 9144, 9912, 11064, 12216, 12960, 14112, 15264, 15840, 16992, 18336, 19080, 19848, 21384, 22152, 22920, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, 31704, 32856, 34008, 35160, 36696, 36696, 37888, 39232, 40576, 40576, 42368, 43816, 43816, 45352, 46888, 46888, 48936, 48936, 51024, 51024, 52752, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 61664, 61664, 63776, 63776, 63776, 66592, 66592, 68808, 68808, 71112, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 78704, 78704, 78704, 81176, 81176, 81176, 84760, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 93800, 97896, 97896, 97896, 97896, 101840, 101840, 101840, 101840, 105528, 105528, 105528, 105528, 110136, 110136, 110136}, + {1064, 2152, 3240, 4264, 5352, 6456, 7480, 8504, 9528, 10680, 11832, 12960, 14112, 15264, 16416, 16992, 18336, 19080, 20616, 21384, 22920, 23688, 24496, 25456, 27376, 28336, 29296, 30576, 31704, 32856, 34008, 34008, 35160, 36696, 37888, 39232, 40576, 40576, 42368, 43816, 43816, 45352, 46888, 46888, 48936, 48936, 51024, 51024, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 61664, 61664, 63776, 63776, 66592, 66592, 68808, 68808, 68808, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 78704, 78704, 81176, 81176, 81176, 84760, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 97896, 97896, 97896, 97896, 101840, 101840, 101840, 101840, 105528, 105528, 105528, 110136, 110136, 110136, 110136, 115040, 115040, 115040, 115040, 119816, 119816, 119816}, + {1128, 2280, 3496, 4584, 5736, 6968, 7992, 9144, 10296, 11448, 12576, 13536, 14688, 15840, 16992, 18336, 19848, 20616, 22152, 22920, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 40576, 42368, 43816, 45352, 45352, 46888, 48936, 48936, 51024, 51024, 52752, 55056, 55056, 57336, 57336, 59256, 59256, 61664, 61664, 63776, 63776, 66592, 66592, 68808, 68808, 71112, 71112, 73712, 73712, 76208, 76208, 76208, 78704, 78704, 81176, 81176, 81176, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 97896, 97896, 97896, 101840,101840,101840,101840,105528, 105528, 105528, 110136, 110136, 110136, 110136, 115040, 115040, 115040, 115040, 119816, 119816, 119816, 119816, 124464, 124464, 124464, 124464, 128496}, + {1192, 2408, 3624, 4968, 5992, 7224, 8504, 9912, 11064, 12216, 13536, 14688, 15840, 16992, 18336, 19848, 20616, 22152, 22920, 24496, 25456, 26416, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 42368, 43816, 45352, 46888, 46888, 48936, 51024, 51024, 52752, 52752, 55056, 57336, 57336, 59256, 59256, 61664, 61664, 63776, 63776, 66592, 66592, 68808, 71112, 71112, 73712, 73712, 73712, 76208, 76208, 78704, 78704, 81176, 81176, 84760, 84760, 84760, 87936, 87936, 90816, 90816, 90816, 93800, 93800, 93800, 97896, 97896, 97896, 101840, 101840, 101840, 105528, 105528, 105528, 105528, 110136, 110136, 110136, 115040, 115040, 115040, 115040, 119816, 119816, 119816, 124464, 124464, 124464, 124464, 128496, 128496, 128496, 128496, 133208, 133208, 133208, 133208}, + {1256, 2536, 3752, 5160, 6200, 7480, 8760, 10296, 11448, 12576, 14112, 15264, 16416, 17568, 19080, 20616, 21384, 22920, 24496, 25456, 26416, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 43816, 43816, 45352, 46888, 48936, 48936, 51024, 52752, 52752, 55056, 55056, 57336, 59256, 59256, 61664, 61664, 63776, 63776, 66592, 66592, 68808, 71112, 71112, 73712, 73712, 76208, 76208, 78704, 78704, 81176, 81176, 81176, 84760, 84760, 87936, 87936, 87936, 90816, 90816, 93800, 93800, 93800, 97896, 97896, 97896, 101840, 101840, 101840, 105528, 105528, 105528, 110136, 110136, 110136, 110136, 115040,115040, 115040, 119816, 119816, 119816, 124464, 124464, 124464, 124464, 128496, 128496, 128496, 128496, 133208, 133208, 133208, 133208, 137792, 137792, 137792, 142248}, + {1480, 2984, 4392, 5992, 7480, 8760, 10296, 11832, 13536, 14688, 16416, 17568, 19080, 20616, 22152, 23688, 25456, 26416, 28336, 29296, 30576, 32856, 34008, 35160, 36696, 37888, 40576, 40576, 42368, 43816, 45352, 46888, 48936, 51024, 52752, 52752, 55056, 55056, 57336, 59256, 59256, 61664, 63776, 63776, 66592, 68808, 68808, 71112, 73712, 75376, 75376, 75376, 75376, 75376, 75376, 81176, 84760, 84760, 87936, 87936, 90816, 90816, 93800, 93800, 97896, 97896, 97896, 101840, 101840, 105528, 105528, 105528, 110136, 110136, 110136, 110136, 115040, 115040, 115040, 119816, 119816, 119816, 124464, 124464, 124464, 128496, 128496, 128496, 133208, 133208, 133208, 137792, 137792, 137792, 142248, 142248, 142248, 146856, 146856,149776, 149776, 149776, 149776, 149776, 149776, 149776, 149776, 149776, 149776, 149776} + } +}; +RgSchUlIMcsTbl rgUlIMcsTbl = { + {2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}, {2, 5}, + {2, 6}, {2, 7}, {2, 8}, {2, 9}, {2, 10}, + {4, 10}, {4, 11}, {4, 12}, {4, 13}, {4, 14}, + {4, 15}, {4, 16}, {4, 17}, {4, 18}, {4, 19}, + {6, 19}, {6, 20}, {6, 21}, {6, 22}, {6, 23}, + {6, 24}, {6, 25}, {6, 26} +}; +RgSchUeCatTbl rgUeCatTbl = { + /*Column1:Maximum number of bits of an UL-SCH + transport block transmitted within a TTI + - maxUlBits + Column2:Maximum number of bits of a DLSCH + transport block received within a TTI + - maxDlBits + Column3:Total number of soft channel bits + - maxSftChBits + Column4:Support for 64QAM in UL + - ul64qamSup + Column5:Maximum number of DL-SCH transport + block bits received within a TTI + - maxDlTbBits + Column6:Maximum number of supported layers for + spatial multiplexing in DL + - maxTxLyrs*/ + {5160, {10296,0}, 250368, FALSE, 10296, 1}, + {25456, {51024,0}, 1237248, FALSE, 51024, 2}, + {51024, {75376,0}, 1237248, FALSE, 102048, 2}, + {51024, {75376,0}, 1827072, FALSE, 150752, 2}, + {75376, {149776,0}, 3667200, TRUE, 299552, 4}, + {51024, {75376,149776}, 3654144, FALSE, 301504, 4}, + {51024, {75376,149776}, 3654144, FALSE, 301504, 4}, + {149776,{299856,0}, 35982720,TRUE, 2998560, 8} +}; + +/* [ccpu00138532]-ADD-The below table stores the min HARQ RTT time + in Downlink for TDD and FDD. Indices 0 to 6 map to tdd UL DL config 0-6. + Index 7 map to FDD */ +U8 rgSchCmnHarqRtt[8] = {4,7,10,9,12,15,6,8}; +/* Number of CFI Switchover Index is equals to 7 TDD Indexes + 1 FDD index */ +U8 rgSchCfiSwitchOvrWinLen[] = {7, 4, 2, 3, 2, 1, 6, 8}; + +/* EffTbl is calculated for single layer and two layers. + * CqiToTbs is calculated for single layer and two layers */ +RgSchCmnTbSzEff rgSchCmnNorCfi1Eff[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnNorCfi2Eff[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnTbSzEff rgSchCmnNorCfi3Eff[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnNorCfi4Eff[RGSCH_MAX_NUM_LYR_PERCW]; +/* New variable to store UL effiency values for normal and extended CP*/ +RgSchCmnTbSzEff rgSchCmnNorUlEff[1],rgSchCmnExtUlEff[1]; +RgSchCmnCqiToTbs rgSchCmnNorCfi1CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnNorCfi2CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnCqiToTbs rgSchCmnNorCfi3CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnNorCfi4CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnCqiToTbs *rgSchCmnCqiToTbs[RGSCH_MAX_NUM_LYR_PERCW][RG_SCH_CMN_MAX_CP][RG_SCH_CMN_MAX_CFI]; +RgSchCmnTbSzEff rgSchCmnExtCfi1Eff[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnExtCfi2Eff[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnTbSzEff rgSchCmnExtCfi3Eff[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnExtCfi4Eff[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnCqiToTbs rgSchCmnExtCfi1CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnExtCfi2CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW]; +RgSchCmnCqiToTbs rgSchCmnExtCfi3CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW], rgSchCmnExtCfi4CqiToTbs[RGSCH_MAX_NUM_LYR_PERCW]; +/* Include CRS REs while calculating Efficiency */ +RgSchCmnTbSzEff *rgSchCmnEffTbl[RGSCH_MAX_NUM_LYR_PERCW][RG_SCH_CMN_MAX_CP][RG_SCH_CMN_MAX_ANT_CONF][RG_SCH_CMN_MAX_CFI]; +RgSchCmnTbSzEff *rgSchCmnUlEffTbl[RG_SCH_CMN_MAX_CP]; +#ifdef LTE_TDD +RgSchRaPrmblToRaFrmTbl rgRaPrmblToRaFrmTbl = {1, 2, 2, 3, 1}; +#else +/* Added matrix 'rgRaPrmblToRaFrmTbl'for computation of RA sub-frames from RA preamble */ +RgSchRaPrmblToRaFrmTbl rgRaPrmblToRaFrmTbl = {1, 2, 2, 3}; +#endif + +EXTERN RgUlSchdInits rgSchUlSchdInits; +EXTERN RgDlSchdInits rgSchDlSchdInits; +EXTERN RgDlfsSchdInits rgSchDlfsSchdInits; +#ifdef EMTC_ENABLE +EXTERN RgEmtcUlSchdInits rgSchEmtcUlSchdInits; +EXTERN RgEmtcDlSchdInits rgSchEmtcDlSchdInits; +#endif + +/* RACHO : start */ +PRIVATE S16 rgSCHCmnUeIdleExdThrsld ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PUBLIC RgSchUeCb* rgSCHCmnGetHoUe ARGS(( +RgSchCellCb *cell, +U16 rapId +)); +PRIVATE Void rgSCHCmnDelDedPreamble ARGS(( +RgSchCellCb *cell, +U8 preambleId +)); +PUBLIC RgSchUeCb* rgSCHCmnGetPoUe ARGS(( +RgSchCellCb *cell, +U16 rapId, +CmLteTimingInfo timingInfo +)); +PRIVATE Void rgSCHCmnDelRachInfo ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE S16 rgSCHCmnUlRbAllocForPoHoUe ARGS(( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUeCb *ue, +U8 maxRb +)); +PRIVATE Void rgSCHCmnHdlHoPo ARGS(( +RgSchCellCb *cell, +CmLListCp *raRspLst, +RgSchRaReqInfo *raReq +)); +PRIVATE Void rgSCHCmnAllocPoHoGrnt ARGS(( +RgSchCellCb *cell, +CmLListCp *raRspLst, +RgSchUeCb *ue, +RgSchRaReqInfo *raReq +)); +PRIVATE Void rgSCHCmnFillPdcchOdr2Sf ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchPdcch *pdcc, +U8 rapId, +U8 prachMskIdx +)); +PRIVATE Void rgSCHCmnDlAdd2PdcchOdrQ ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE Void rgSCHCmnDlRmvFrmPdcchOdrQ ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE Void rgSCHCmnUpdNxtPrchMskIdx ARGS(( +RgSchCellCb *cell +)); +PRIVATE Void rgSCHCmnUpdRachParam ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnAllocPOParam ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchUeCb *ue, +RgSchPdcch **pdcch, +U8 *rapId, +U8 *prachMskIdx +)); +PRIVATE Void rgSCHCmnGenPdcchOrder ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf +)); +PRIVATE Void rgSCHCmnCfgRachDedPrm ARGS(( +RgSchCellCb *cell +)); +/* RACHO : end */ + +PRIVATE Void rgSCHCmnHdlUlInactUes ARGS(( +RgSchCellCb *cell +)); +PRIVATE Void rgSCHCmnHdlDlInactUes ARGS(( +RgSchCellCb *cell +)); +PRIVATE Void rgSCHCmnUlInit ARGS((Void +)); +PRIVATE Void rgSCHCmnDlInit ARGS((Void +)); +PRIVATE Void rgSCHCmnInitDlRbAllocInfo ARGS(( +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnUpdUlCompEffBsr ARGS(( +RgSchUeCb *ue +)); +#if RG_UNUSED +PRIVATE Void rgSCHCmnUlSetAllUnSched ARGS(( +RgSchCmnUlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnUlUpdSf ARGS(( + RgSchCellCb *cell, + RgSchCmnUlRbAllocInfo *allocInfo, + RgSchUlSf *sf + )); +PRIVATE Void rgSCHCmnUlHndlAllocRetx ARGS(( + RgSchCellCb *cell, + RgSchCmnUlRbAllocInfo *allocInfo, + RgSchUlSf *sf, + RgSchUlAlloc *alloc + )); +#endif +PRIVATE Void rgSCHCmnGrpPwrCntrlPucch ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf +)); +PRIVATE Void rgSCHCmnGrpPwrCntrlPusch ARGS(( +RgSchCellCb *cell, +RgSchUlSf *ulSf +)); +PRIVATE Void rgSCHCmnDelUeFrmRefreshQ ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE S16 rgSCHCmnTmrExpiry ARGS(( +PTR cb, /* Pointer to timer control block */ +S16 tmrEvnt /* Timer Event */ +)); +PRIVATE S16 rgSCHCmnTmrProc ARGS(( +RgSchCellCb *cell +)); +PRIVATE Void rgSCHCmnAddUeToRefreshQ ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 wait +)); +PRIVATE Void rgSCHCmnDlCcchRetx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnUpdUeMimoInfo ARGS(( +RgrUeCfg *ueCfg, +RgSchCmnDlUe *ueDl, +RgSchCellCb *cell, +RgSchCmnCell *cellSchd +)); +PRIVATE Void rgSCHCmnUpdUeUlCqiInfo ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchCmnUlUe *ueUl, +RgSchCmnUe *ueSchCmn, +RgSchCmnCell *cellSchd, +Bool isEcp +)); +#ifdef RGR_V1 +PRIVATE Void rgSCHCmnDlCcchSduRetx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnDlCcchSduTx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE S16 rgSCHCmnCcchSduAlloc ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ueCb, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE S16 rgSCHCmnCcchSduDedAlloc ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ueCb +)); +PRIVATE S16 rgSCHCmnNonDlfsCcchSduRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ueCb, +RgSchDlSf *dlSf +)); +#endif +PRIVATE Void rgSCHCmnInitVars ARGS(( + RgSchCellCb *cell + )); + +/*ccpu00117180 - DEL - Moved rgSCHCmnUpdVars to .x as its access is now PUBLIC */ +PRIVATE Void rgSCHCmnUlRbAllocForLst ARGS(( + RgSchCellCb *cell, + RgSchUlSf *sf, + U32 count, + CmLListCp *reqLst, + CmLListCp *schdLst, + CmLListCp *nonSchdLst, + Bool isNewTx + )); +PRIVATE S16 rgSCHCmnUlRbAllocForUe ARGS(( + RgSchCellCb *cell, + RgSchUlSf *sf, + RgSchUeCb *ue, + U8 maxRb, + RgSchUlHole *hole + )); +PRIVATE Void rgSCHCmnMsg3GrntReq ARGS(( + RgSchCellCb *cell, + CmLteRnti rnti, + Bool preamGrpA, + RgSchUlHqProcCb *hqProc, + RgSchUlAlloc **ulAllocRef, + U8 *hqProcIdRef + )); +PRIVATE Void rgSCHCmnUlNonadapRetx ARGS(( + RgSchCmnUlCell *cellUl, + RgSchUlAlloc *alloc, + U8 idx + )); + +PRIVATE Void rgSCHCmnDlCcchRarAlloc ARGS(( +RgSchCellCb *cell +)); +PRIVATE Void rgSCHCmnDlCcchTx ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnDlBcchPcch ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgInfSfAlloc *subfrmAlloc +)); +PUBLIC Bool rgSCHCmnChkInWin ARGS(( +CmLteTimingInfo frm, +CmLteTimingInfo start, +CmLteTimingInfo end +)); +PUBLIC Bool rgSCHCmnChkPastWin ARGS(( +CmLteTimingInfo frm, +CmLteTimingInfo end +)); +PRIVATE Void rgSCHCmnClcAlloc ARGS(( +RgSchCellCb *cell, +RgSchDlSf *sf, +RgSchClcDlLcCb *lch, +U16 rnti, +RgSchCmnDlRbAllocInfo *allocInfo +)); +#ifndef LTEMAC_SPS +PRIVATE Void rgSCHCmnClcRbAlloc ARGS(( +RgSchCellCb *cell, +U32 bo, +U8 cqi, +U8 *rb, +U32 *tbs, +U8 *mcs, +RgSchDlSf *sf +)); +#endif + +PRIVATE S16 rgSCHCmnMsg4Alloc ARGS(( +RgSchCellCb *cell, +RgSchRaCb *raCb, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE S16 rgSCHCmnMsg4DedAlloc ARGS(( +RgSchCellCb *cell, +RgSchRaCb *raCb +)); +PRIVATE Void rgSCHCmnDlRaRsp ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE S16 rgSCHCmnRaRspAlloc ARGS(( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +U16 rntiIdx, +U16 rarnti, +U8 noRaRnti, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnUlUeDelAllocs ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue +)); +PRIVATE Void rgSCHCmnDlSetUeAllocLmt ARGS(( +RgSchCellCb *cell, +RgSchCmnDlUe *ueDl, +Bool isEmtcUe +)); +PRIVATE S16 rgSCHCmnDlRgrCellCfg ARGS(( +RgSchCellCb *cell, +RgrCellCfg *cfg, +RgSchErrInfo *err +)); +PRIVATE Void rgSCHCmnUlAdapRetx ARGS(( +RgSchUlAlloc *alloc, +RgSchUlHqProcCb *proc +)); +PRIVATE Void rgSCHCmnUlUpdAllocRetx ARGS(( +RgSchCellCb *cell, +RgSchUlAlloc *alloc +)); +PRIVATE Void rgSCHCmnUlSfReTxAllocs ARGS(( +RgSchCellCb *cell, +RgSchUlSf *sf +)); +/* Fix: syed Adaptive Msg3 Retx crash. */ +PRIVATE Void rgSCHCmnUlSfRlsRetxProcs ARGS(( +RgSchCellCb *cell, +RgSchUlSf *sf +)); + +#ifdef TFU_UPGRADE +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg ARGS +(( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeRecfg *ueRecfg, +U8 numTxPorts +)); +#else +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg ARGS +(( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeRecfg *ueRecfg +)); +#endif + + +/* + * DL RB allocation specific functions + */ + +PRIVATE Void rgSCHCmnDlRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE Void rgSCHCmnNonDlfsRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +)); +PRIVATE S16 rgSCHCmnNonDlfsCmnRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *cmnAllocInfo)); + +#ifndef LTE_TDD +PRIVATE Void rgSCHCmnNonDlfsPbchRbAllocAdj ARGS(( +RgSchCellCb *cell, +RgSchDlRbAlloc *cmnAllocInfo, +U8 pbchSsRsSym, +Bool isBcchPcch +)); +/* Added function to adjust TBSize*/ +PRIVATE Void rgSCHCmnNonDlfsPbchTbSizeAdj ARGS(( +RgSchDlRbAlloc *allocInfo, +U8 numOvrlapgPbchRb, +U8 pbchSsRsSym, +U8 idx, +U32 bytesReq +)); + +/* Added function to find num of overlapping PBCH rb*/ +PRIVATE Void rgSCHCmnFindNumPbchOvrlapRbs ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +U8 *numOvrlapgPbchRb +)); + +PRIVATE U8 rgSCHCmnFindNumAddtlRbsAvl ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo +)); +#ifdef DEBUGP +PRIVATE Void rgSCHCmnFindCodeRate ARGS(( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +U8 idx +)); +#endif +#endif +PRIVATE Void rgSCHCmnNonDlfsMsg4Alloc ARGS(( +RgSchCellCb *cell, +RgSchCmnMsg4RbAlloc *msg4AllocInfo, +U8 isRetx +)); +PRIVATE S16 rgSCHCmnNonDlfsMsg4RbAlloc ARGS(( +RgSchCellCb *cell, +RgSchRaCb *raCb, +RgSchDlSf *dlSf +)); + +PRIVATE S16 rgSCHCmnNonDlfsUeRbAlloc ARGS(( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *dlSf, +U8 *isDlBwAvail +)); +#ifndef LTEMAC_SPS +PRIVATE U32 rgSCHCmnCalcRiv ARGS(( U8 bw, + U8 rbStart, + U8 numRb)); +#endif + +#ifdef LTE_TDD +PRIVATE Void rgSCHCmnUpdHqAndDai ARGS(( +RgSchDlHqProcCb *hqP, +RgSchDlSf *subFrm, +RgSchDlHqTbCb *tbCb, +U8 tbAllocIdx +)); +PRIVATE S16 rgSCHCmnUlCalcAvailBw ARGS(( +RgSchCellCb *cell, +RgrCellCfg *cellCfg, +U8 cfi, +U8 *rbStartRef, +U8 *bwAvailRef +)); +PRIVATE S16 rgSCHCmnDlKdashUlAscInit ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnDlANFdbkInit ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnDlNpValInit ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnDlCreateRachPrmLst ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnDlCpyRachInfo ARGS(( +RgSchCellCb *cell, +RgSchTddRachRspLst rachRspLst[][RGSCH_NUM_SUB_FRAMES], +U8 raArrSz +)); +PRIVATE S16 rgSCHCmnDlRachInfoInit ARGS(( +RgSchCellCb *cell +)); +PRIVATE S16 rgSCHCmnDlPhichOffsetInit ARGS(( +RgSchCellCb *cell +)); +#endif +#ifdef TFU_UPGRADE +PRIVATE Void rgSCHCmnFindUlCqiUlTxAnt ARGS +(( + RgSchCellCb *cell, + RgSchUeCb *ue, + U8 wideCqi + )); + PRIVATE RgSchCmnRank rgSCHCmnComputeRank ARGS +(( + RgrTxMode txMode, + U32 *pmiBitMap, + U8 numTxPorts + )); + + PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode3 ARGS +(( + U32 *pmiBitMap + )); + + PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode3 ARGS +(( + U32 *pmiBitMap + )); + + PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode4 ARGS +(( + U32 *pmiBitMap + )); + + PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode4 ARGS +(( + U32 *pmiBitMap + )); + + PRIVATE U8 rgSCHCmnCalcWcqiFrmSnr ARGS +(( + RgSchCellCb *cell, + TfuSrsRpt *srsRpt + )); +#endif + +/* comcodsepa : start */ + +/** + * @brief This function computes efficiency and stores in a table. + * + * @details + * + * Function: rgSCHCmnCompEff + * Purpose: this function computes the efficiency as number of + * bytes per 1024 symbols. The CFI table is also filled + * with the same information such that comparison is valid + * + * Invoked by: Scheduler + * + * @param[in] U8 noPdcchSym + * @param[in] U8 cpType + * @param[in] U8 txAntIdx + * @param[in] RgSchCmnTbSzEff* effTbl + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnCompEff +( +U8 noPdcchSym, +U8 cpType, +U8 txAntIdx, +RgSchCmnTbSzEff *effTbl +) +#else +PRIVATE Void rgSCHCmnCompEff(noPdcchSym, cpType, txAntIdx, effTbl) +U8 noPdcchSym; +U8 cpType; +U8 txAntIdx; +RgSchCmnTbSzEff *effTbl; +#endif +{ + U8 noResPerRb; + U8 noSymPerRb; + U8 resOfCrs; /* Effective REs occupied by CRS */ + U8 i, j; + + TRC2(rgSCHCmnCompEff); + + switch (cpType) + { + case RG_SCH_CMN_NOR_CP: + noSymPerRb = 14; + break; + case RG_SCH_CMN_EXT_CP: + noSymPerRb = 12; + break; + default: + /* Generate a log error. This case should never be executed */ + RETVOID; + } + + /* Depending on the Tx Antenna Index, deduct the + * Resource elements for the CRS */ + switch (txAntIdx) + { + case 0: + resOfCrs = RG_SCH_CMN_EFF_CRS_ONE_ANT_PORT; + break; + case 1: + resOfCrs = RG_SCH_CMN_EFF_CRS_TWO_ANT_PORT; + break; + case 2: + resOfCrs = RG_SCH_CMN_EFF_CRS_FOUR_ANT_PORT; + break; + default: + /* Generate a log error. This case should never be executed */ + RETVOID; + } + noResPerRb = ((noSymPerRb - noPdcchSym) * RB_SCH_CMN_NUM_SCS_PER_RB) - resOfCrs; + for (i = 0; i < RG_SCH_CMN_NUM_TBS; i++) + { + (*effTbl)[i] = 0; + for (j = 0; j < RG_SCH_CMN_NUM_RBS; j++) + { + /* This line computes the coding efficiency per 1024 REs */ + (*effTbl)[i] += (rgTbSzTbl[0][i][j] * 1024) / (noResPerRb * (j+1)); + } + (*effTbl)[i] /= RG_SCH_CMN_NUM_RBS; + } + RETVOID; +} +/** + * @brief This function computes efficiency and stores in a table. + * + * @details + * + * Function: rgSCHCmnCompUlEff + * Purpose: this function computes the efficiency as number of + * bytes per 1024 symbols. The CFI table is also filled + * with the same information such that comparison is valid + * + * Invoked by: Scheduler + * + * @param[in] U8 noUlRsSym + * @param[in] U8 cpType + * @param[in] U8 txAntIdx + * @param[in] RgSchCmnTbSzEff* effTbl + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnCompUlEff +( +U8 noUlRsSym, +U8 cpType, +RgSchCmnTbSzEff *effTbl +) +#else +PRIVATE Void rgSCHCmnCompUlEff(noUlRsSym, cpType, effTbl) +U8 noUlRsSym; +U8 cpType; +RgSchCmnTbSzEff *effTbl; +#endif +{ + U8 noResPerRb; + U8 noSymPerRb; + U8 i, j; + + TRC2(rgSCHCmnCompUlEff); + + switch (cpType) + { + case RG_SCH_CMN_NOR_CP: + noSymPerRb = 14; + break; + case RG_SCH_CMN_EXT_CP: + noSymPerRb = 12; + break; + default: + /* Generate a log error. This case should never be executed */ + RETVOID; + } + + noResPerRb = ((noSymPerRb - noUlRsSym) * RB_SCH_CMN_NUM_SCS_PER_RB); + for (i = 0; i < RG_SCH_CMN_NUM_TBS; i++) + { + (*effTbl)[i] = 0; + for (j = 0; j < RG_SCH_CMN_NUM_RBS; j++) + { + /* This line computes the coding efficiency per 1024 REs */ + (*effTbl)[i] += (rgTbSzTbl[0][i][j] * 1024) / (noResPerRb * (j+1)); + } + (*effTbl)[i] /= RG_SCH_CMN_NUM_RBS; + } + RETVOID; +} + +/** + * @brief This function computes efficiency for 2 layers and stores in a table. + * + * @details + * + * Function: rgSCHCmn2LyrCompEff + * Purpose: this function computes the efficiency as number of + * bytes per 1024 symbols. The CFI table is also filled + * with the same information such that comparison is valid + * + * Invoked by: Scheduler + * + * @param[in] U8 noPdcchSym + * @param[in] U8 cpType + * @param[in] U8 txAntIdx + * @param[in] RgSchCmnTbSzEff* effTbl2Lyr + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmn2LyrCompEff +( +U8 noPdcchSym, +U8 cpType, +U8 txAntIdx, +RgSchCmnTbSzEff *effTbl2Lyr +) +#else +PRIVATE Void rgSCHCmn2LyrCompEff(noPdcchSym, cpType, txAntIdx, effTbl2Lyr) +U8 noPdcchSym; +U8 cpType; +U8 txAntIdx; +RgSchCmnTbSzEff *effTbl2Lyr; +#endif +{ + U8 noResPerRb; + U8 noSymPerRb; + U8 resOfCrs; /* Effective REs occupied by CRS */ + U8 i, j; + + TRC2(rgSCHCmn2LyrCompEff); + + switch (cpType) + { + case RG_SCH_CMN_NOR_CP: + noSymPerRb = 14; + break; + case RG_SCH_CMN_EXT_CP: + noSymPerRb = 12; + break; + default: + /* Generate a log error. This case should never be executed */ + RETVOID; + } + + /* Depending on the Tx Antenna Index, deduct the + * Resource elements for the CRS */ + switch (txAntIdx) + { + case 0: + resOfCrs = RG_SCH_CMN_EFF_CRS_ONE_ANT_PORT; + break; + case 1: + resOfCrs = RG_SCH_CMN_EFF_CRS_TWO_ANT_PORT; + break; + case 2: + resOfCrs = RG_SCH_CMN_EFF_CRS_FOUR_ANT_PORT; + break; + default: + /* Generate a log error. This case should never be executed */ + RETVOID; + } + + noResPerRb = ((noSymPerRb - noPdcchSym) * RB_SCH_CMN_NUM_SCS_PER_RB) - resOfCrs; + for (i = 0; i < RG_SCH_CMN_NUM_TBS; i++) + { + (*effTbl2Lyr)[i] = 0; + for (j = 0; j < RG_SCH_CMN_NUM_RBS; j++) + { + /* This line computes the coding efficiency per 1024 REs */ + (*effTbl2Lyr)[i] += (rgTbSzTbl[1][i][j] * 1024) / (noResPerRb * (j+1)); + } + (*effTbl2Lyr)[i] /= RG_SCH_CMN_NUM_RBS; + } + RETVOID; +} + + +/** + * @brief This function initializes the rgSchCmnDciFrmtSizes table. + * + * @details + * + * Function: rgSCHCmnGetDciFrmtSizes + * Purpose: This function determines the sizes of all + * the available DCI Formats. The order of + * bits addition for each format is inaccordance + * with the specs. + * Invoked by: rgSCHCmnRgrCellCfg + * + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGetDciFrmtSizes +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnGetDciFrmtSizes(cell) +RgSchCellCb *cell; +#endif +{ + + TRC2(rgSCHCmnGetDciFrmtSizes); + + /* DCI Format 0 size determination */ + rgSchCmnDciFrmtSizes[0] = 1 + + 1 + + rgSCHUtlLog32bitNbase2((cell->bwCfg.ulTotalBw * \ + (cell->bwCfg.ulTotalBw + 1))/2) + + 5 + + 1 + + 2 + + 3 + +#ifdef LTE_TDD + 2 + + 2 + +#endif + 1; + /* DCI Format 1 size determination */ + rgSchCmnDciFrmtSizes[1] = 1 + + RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize) + + 5 + +#ifndef LTE_TDD + 3 + +#else + 4 + 2 + /* HqProc Id and DAI */ +#endif + 1 + + 2 + + 2; + + /* DCI Format 1A size determination */ + rgSchCmnDciFrmtSizes[2] = 1 + /* Flag for format0/format1a differentiation */ + 1 + /* Localized/distributed VRB assignment flag */ + 5 + /* For mcs */ +#ifndef LTE_TDD + 3 + /* Harq process Id */ +#else + 4 + /* Harq process Id */ + 2 + /* UL Index or DAI */ +#endif + 1 + /* New Data Indicator */ + 2 + /* For RV */ + 2 + /* For tpc */ + 1 + rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw * \ + (cell->bwCfg.dlTotalBw + 1))/2); + /* Resource block assignment ceil[log2(bw(bw+1)/2)] : \ + Since VRB is local */ + + /* DCI Format 1B size determination */ + rgSchCmnDciFrmtSizes[3] = 1 + + rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw * \ + (cell->bwCfg.dlTotalBw + 1))/2) + + 5 + + 3 + +#ifdef LTE_TDD + 1 + /* HqP */ + 2 + /* Dai */ +#endif + 1 + + 2 + + 2 + + ((cell->numTxAntPorts == 4)? 4:2) + + 1; + + /* DCI Format 1C size determination */ + /* Approximation: NDLVrbGap1 ~= Nprb for DL */ + rgSchCmnDciFrmtSizes[4] = (cell->bwCfg.dlTotalBw < 50)? 0:1 + + (cell->bwCfg.dlTotalBw < 50)? + (rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw/2 * \ + (cell->bwCfg.dlTotalBw/2 + 1))/2)) : + (rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw/4 * \ + (cell->bwCfg.dlTotalBw/4 + 1))/2)) + + 5; + + /* DCI Format 1D size determination */ + rgSchCmnDciFrmtSizes[5] = 1 + + rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw * \ + (cell->bwCfg.dlTotalBw + 1))/2) + + 5 + + 3 + +#ifdef LTE_TDD + 1 + 2 + +#endif + 1 + + 2 + + 2 + + ((cell->numTxAntPorts == 4)? 4:2) + + 1; + + /* DCI Format 2 size determination */ + rgSchCmnDciFrmtSizes[6] = ((cell->bwCfg.dlTotalBw < 10)?0:1) + + RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize) + + 2 + +#ifdef LTE_TDD + 2 + 1 + +#endif + 3 + + 1 + + (5 + 1 + 2)*2 + + ((cell->numTxAntPorts == 4)? 6:3); + + /* DCI Format 2A size determination */ + rgSchCmnDciFrmtSizes[7] = ((cell->bwCfg.dlTotalBw < 10)?0:1) + + RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize) + + 2 + +#ifdef LTE_TDD + 2 + 1 + +#endif + 3 + + 1 + + (5 + 1 + 2)*2 + + ((cell->numTxAntPorts == 4)? 2:0); + + /* DCI Format 3 size determination */ + rgSchCmnDciFrmtSizes[8] = rgSchCmnDciFrmtSizes[0]; + + /* DCI Format 3A size determination */ + rgSchCmnDciFrmtSizes[9] = rgSchCmnDciFrmtSizes[0]; + + RETVOID; +} + + +/** + * @brief This function initializes the cmnCell->dciAggrLvl table. + * + * @details + * + * Function: rgSCHCmnGetCqiDciFrmt2AggrLvl + * Purpose: This function determines the Aggregation level + * for each CQI level against each DCI format. + * Invoked by: rgSCHCmnRgrCellCfg + * + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGetCqiDciFrmt2AggrLvl +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnGetCqiDciFrmt2AggrLvl(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 i; + U8 j; + + TRC2(rgSCHCmnGetCqiDciFrmt2AggrLvl); + + for (i = 0; i < RG_SCH_CMN_MAX_CQI; i++) + { + for (j = 0; j < 10; j++) + { + U32 pdcchBits; /* Actual number of phy bits needed for a given DCI Format + * for a given CQI Level */ + pdcchBits = (rgSchCmnDciFrmtSizes[j] * 1024)/rgSchCmnCqiPdcchEff[i]; + /* V5G_211 : 6.6 */ + if (pdcchBits < 192) + { + cellSch->dciAggrLvl[i][j] = CM_LTE_AGGR_LVL2; + continue; + } + if (pdcchBits < 384) + { + cellSch->dciAggrLvl[i][j] = CM_LTE_AGGR_LVL4; + continue; + } + if (pdcchBits < 768) + { + cellSch->dciAggrLvl[i][j] = CM_LTE_AGGR_LVL8; + continue; + } + cellSch->dciAggrLvl[i][j] = CM_LTE_AGGR_LVL16; + } + } + RETVOID; +} + +/** + * @brief This function initializes all the data for the scheduler. + * + * @details + * + * Function: rgSCHCmnDlInit + * Purpose: This function initializes the following information: + * 1. Efficiency table + * 2. CQI to table index - It is one row for upto 3 RBs + * and another row for greater than 3 RBs + * currently extended prefix is compiled out. + * Invoked by: MAC intialization code..may be ActvInit + * + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlInit +( +) +#else +PRIVATE Void rgSCHCmnDlInit() +#endif +{ + U8 i; + S16 j; + S16 k; + U8 idx; + RgSchCmnTbSzEff *effTbl; + RgSchCmnCqiToTbs *tbsTbl; + + TRC2(rgSCHCmnDlInit); + + /* 0 corresponds to Single layer case, 1 corresponds to 2 layers case*/ + /* Init Efficiency table for normal cyclic prefix */ + /*Initialize Efficiency table for Layer Index 0 */ + /*Initialize Efficiency table for Tx Antenna Port Index 0 */ + /*Initialize Efficiency table for each of the CFI indices. The + * 4th Dimension of the rgSCHCmnEffTbl table refers to the CFI Index*/ + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][0][0] = &rgSchCmnNorCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][0][1] = &rgSchCmnNorCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][0][2] = &rgSchCmnNorCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][0][3] = &rgSchCmnNorCfi4Eff[0]; + /*Initialize Efficency table for Tx Antenna Port Index 1 */ + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][1][0] = &rgSchCmnNorCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][1][1] = &rgSchCmnNorCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][1][2] = &rgSchCmnNorCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][1][3] = &rgSchCmnNorCfi4Eff[0]; + /*Initialize Efficency table for Tx Antenna Port Index 2 */ + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][2][0] = &rgSchCmnNorCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][2][1] = &rgSchCmnNorCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][2][2] = &rgSchCmnNorCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][2][3] = &rgSchCmnNorCfi4Eff[0]; + + /*Initialize CQI to TBS table for Layer Index 0 for Normal CP */ + rgSchCmnCqiToTbs[0][RG_SCH_CMN_NOR_CP][0] = &rgSchCmnNorCfi1CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_NOR_CP][1] = &rgSchCmnNorCfi2CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_NOR_CP][2] = &rgSchCmnNorCfi3CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_NOR_CP][3] = &rgSchCmnNorCfi4CqiToTbs[0]; + + /*Intialize Efficency table for Layer Index 1 */ + /*Initialize Efficiency table for Tx Antenna Port Index 0 */ + /*Initialize Efficiency table for each of the CFI indices. The + * 4th Dimension of the rgSCHCmnEffTbl table refers to the CFI Index*/ + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][0][0] = &rgSchCmnNorCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][0][1] = &rgSchCmnNorCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][0][2] = &rgSchCmnNorCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][0][3] = &rgSchCmnNorCfi4Eff[1]; + /*Initialize Efficiency table for Tx Antenna Port Index 1 */ + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][1][0] = &rgSchCmnNorCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][1][1] = &rgSchCmnNorCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][1][2] = &rgSchCmnNorCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][1][3] = &rgSchCmnNorCfi4Eff[1]; + /*Initialize Efficiency table for Tx Antenna Port Index 2 */ + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][2][0] = &rgSchCmnNorCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][2][1] = &rgSchCmnNorCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][2][2] = &rgSchCmnNorCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][2][3] = &rgSchCmnNorCfi4Eff[1]; + + /*Initialize CQI to TBS table for Layer Index 1 for Normal CP */ + rgSchCmnCqiToTbs[1][RG_SCH_CMN_NOR_CP][0] = &rgSchCmnNorCfi1CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_NOR_CP][1] = &rgSchCmnNorCfi2CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_NOR_CP][2] = &rgSchCmnNorCfi3CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_NOR_CP][3] = &rgSchCmnNorCfi4CqiToTbs[1]; + + for (idx = 0; idx < RG_SCH_CMN_MAX_ANT_CONF; idx++) + { + for (i = 0; i < RG_SCH_CMN_MAX_CFI; i++) + { + /* EfficiencyTbl calculation incase of 2 layers for normal CP */ + rgSCHCmnCompEff((U8)(i + 1), RG_SCH_CMN_NOR_CP, idx,\ + rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][idx][i]); + rgSCHCmn2LyrCompEff((U8)(i + 1), RG_SCH_CMN_NOR_CP, idx, \ + rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][idx][i]); + } + } + + for (idx = 0; idx < RG_SCH_CMN_MAX_ANT_CONF; idx++) + { + for (i = 0; i < RG_SCH_CMN_MAX_CFI; i++) + { + effTbl = rgSchCmnEffTbl[0][RG_SCH_CMN_NOR_CP][idx][i]; + tbsTbl = rgSchCmnCqiToTbs[0][RG_SCH_CMN_NOR_CP][i]; + for (j = RG_SCH_CMN_NUM_TBS - 1, k = RG_SCH_CMN_MAX_CQI - 1; + (j >= 0) && (k > 0); --j) + { + /* ADD CQI to MCS mapping correction + * single dimensional array is replaced by 2 dimensions for different CFI*/ + if ((*effTbl)[j] <= rgSchCmnCqiPdschEff[i][k]) + { + (*tbsTbl)[k--] = (U8)j; + } + } + for (; k > 0; --k) + { + (*tbsTbl)[k] = 0; + } + /* effTbl,tbsTbl calculation incase of 2 layers for normal CP */ + effTbl = rgSchCmnEffTbl[1][RG_SCH_CMN_NOR_CP][idx][i]; + tbsTbl = rgSchCmnCqiToTbs[1][RG_SCH_CMN_NOR_CP][i]; + for (j = RG_SCH_CMN_NUM_TBS - 1, k = RG_SCH_CMN_MAX_CQI - 1; + (j >= 0) && (k > 0); --j) + { + /* ADD CQI to MCS mapping correction + * single dimensional array is replaced by 2 dimensions for different CFI*/ + if ((*effTbl)[j] <= rgSchCmn2LyrCqiPdschEff[i][k]) + { + (*tbsTbl)[k--] = (U8)j; + } + } + for (; k > 0; --k) + { + (*tbsTbl)[k] = 0; + } + } + } + + /* Efficiency Table for Extended CP */ + /*Initialize Efficiency table for Layer Index 0 */ + /*Initialize Efficiency table for Tx Antenna Port Index 0 */ + /*Initialize Efficiency table for each of the CFI indices. The + * 4th Dimension of the rgSCHCmnEffTbl table refers to the CFI Index*/ + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][0][0] = &rgSchCmnExtCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][0][1] = &rgSchCmnExtCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][0][2] = &rgSchCmnExtCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][0][3] = &rgSchCmnExtCfi4Eff[0]; + /*Initialize Efficency table for Tx Antenna Port Index 1 */ + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][1][0] = &rgSchCmnExtCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][1][1] = &rgSchCmnExtCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][1][2] = &rgSchCmnExtCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][1][3] = &rgSchCmnExtCfi4Eff[0]; + /*Initialize Efficency table for Tx Antenna Port Index 2 */ + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][2][0] = &rgSchCmnExtCfi1Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][2][1] = &rgSchCmnExtCfi2Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][2][2] = &rgSchCmnExtCfi3Eff[0]; + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][2][3] = &rgSchCmnExtCfi4Eff[0]; + + /*Initialize CQI to TBS table for Layer Index 0 for Extended CP */ + rgSchCmnCqiToTbs[0][RG_SCH_CMN_EXT_CP][0] = &rgSchCmnExtCfi1CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_EXT_CP][1] = &rgSchCmnExtCfi2CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_EXT_CP][2] = &rgSchCmnExtCfi3CqiToTbs[0]; + rgSchCmnCqiToTbs[0][RG_SCH_CMN_EXT_CP][3] = &rgSchCmnExtCfi4CqiToTbs[0]; + + /*Initialize Efficiency table for Layer Index 1 */ + /*Initialize Efficiency table for each of the CFI indices. The + * 4th Dimension of the rgSCHCmnEffTbl table refers to the CFI Index*/ + /*Initialize Efficency table for Tx Antenna Port Index 0 */ + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][0][0] = &rgSchCmnExtCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][0][1] = &rgSchCmnExtCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][0][2] = &rgSchCmnExtCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][0][3] = &rgSchCmnExtCfi4Eff[1]; + /*Initialize Efficency table for Tx Antenna Port Index 1 */ + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][1][0] = &rgSchCmnExtCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][1][1] = &rgSchCmnExtCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][1][2] = &rgSchCmnExtCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][1][3] = &rgSchCmnExtCfi4Eff[1]; + /*Initialize Efficency table for Tx Antenna Port Index 2 */ + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][2][0] = &rgSchCmnExtCfi1Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][2][1] = &rgSchCmnExtCfi2Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][2][2] = &rgSchCmnExtCfi3Eff[1]; + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][2][3] = &rgSchCmnExtCfi4Eff[1]; + + /*Initialize CQI to TBS table for Layer Index 1 for Extended CP */ + rgSchCmnCqiToTbs[1][RG_SCH_CMN_EXT_CP][0] = &rgSchCmnExtCfi1CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_EXT_CP][1] = &rgSchCmnExtCfi2CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_EXT_CP][2] = &rgSchCmnExtCfi3CqiToTbs[1]; + rgSchCmnCqiToTbs[1][RG_SCH_CMN_EXT_CP][3] = &rgSchCmnExtCfi4CqiToTbs[1]; + /* Activate this code when extended cp is supported */ + for (idx = 0; idx < RG_SCH_CMN_MAX_ANT_CONF; idx++) + { + for (i = 0; i < RG_SCH_CMN_MAX_CFI; i++) + { + /* EfficiencyTbl calculation incase of 2 layers for extendedl CP */ + rgSCHCmnCompEff( (U8)(i + 1 ), (U8)RG_SCH_CMN_EXT_CP, idx,\ + rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][idx][i]); + rgSCHCmn2LyrCompEff((U8)(i + 1), (U8) RG_SCH_CMN_EXT_CP,idx, \ + rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][idx][i]); + } + } + + for (idx = 0; idx < RG_SCH_CMN_MAX_ANT_CONF; idx++) + { + for (i = 0; i < RG_SCH_CMN_MAX_CFI; i++) + { + effTbl = rgSchCmnEffTbl[0][RG_SCH_CMN_EXT_CP][idx][i]; + tbsTbl = rgSchCmnCqiToTbs[0][RG_SCH_CMN_EXT_CP][i]; + for (j = RG_SCH_CMN_NUM_TBS - 1, k = RG_SCH_CMN_MAX_CQI - 1; + (j >= 0) && (k > 0); --j) + { + /* ADD CQI to MCS mapping correction + * single dimensional array is replaced by 2 dimensions for different CFI*/ + if ((*effTbl)[j] <= rgSchCmnCqiPdschEff[i][k]) + { + (*tbsTbl)[k--] = (U8)j; + } + } + for (; k > 0; --k) + { + (*tbsTbl)[k] = 0; + } + /* effTbl,tbsTbl calculation incase of 2 layers for extended CP */ + effTbl = rgSchCmnEffTbl[1][RG_SCH_CMN_EXT_CP][idx][i]; + tbsTbl = rgSchCmnCqiToTbs[1][RG_SCH_CMN_EXT_CP][i]; + for (j = RG_SCH_CMN_NUM_TBS - 1, k = RG_SCH_CMN_MAX_CQI - 1; + (j >= 0) && (k > 0); --j) + { + /* ADD CQI to MCS mapping correction + * single dimensional array is replaced by 2 dimensions for different CFI*/ + if ((*effTbl)[j] <= rgSchCmn2LyrCqiPdschEff[i][k]) + { + (*tbsTbl)[k--] = (U8)j; + } + } + for (; k > 0; --k) + { + (*tbsTbl)[k] = 0; + } + } + } + RETVOID; +} + +/** + * @brief This function initializes all the data for the scheduler. + * + * @details + * + * Function: rgSCHCmnUlInit + * Purpose: This function initializes the following information: + * 1. Efficiency table + * 2. CQI to table index - It is one row for upto 3 RBs + * and another row for greater than 3 RBs + * currently extended prefix is compiled out. + * Invoked by: MAC intialization code..may be ActvInit + * + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlInit +( +) +#else +PRIVATE Void rgSCHCmnUlInit() +#endif +{ + U8 *mapTbl = &rgSchCmnUlCqiToTbsTbl[RG_SCH_CMN_NOR_CP][0]; + RgSchCmnTbSzEff *effTbl = &rgSchCmnNorUlEff[0]; + CONSTANT RgSchCmnUlCqiInfo *cqiTbl = &rgSchCmnUlCqiTbl[0]; + S16 i; + S16 j; + TRC2(rgSCHCmnUlInit); + + /* Initaializing new variable added for UL eff */ + rgSchCmnUlEffTbl[RG_SCH_CMN_NOR_CP] = &rgSchCmnNorUlEff[0]; + /* Reason behind using 3 as the number of symbols to rule out for + * efficiency table computation would be that we are using 2 symbols for + * DMRS(1 in each slot) and 1 symbol for SRS*/ + rgSCHCmnCompUlEff(RGSCH_UL_SYM_DMRS_SRS,RG_SCH_CMN_NOR_CP,rgSchCmnUlEffTbl[RG_SCH_CMN_NOR_CP]); + + for (i = RGSCH_NUM_ITBS - 1, j = RG_SCH_CMN_UL_NUM_CQI - 1; + i >= 0 && j > 0; --i) + { + if ((*effTbl)[i] <= cqiTbl[j].eff) + { + mapTbl[j--] = (U8)i; + } + } + for (; j > 0; --j) + { + mapTbl[j] = 0; + } + effTbl = &rgSchCmnExtUlEff[0]; + mapTbl = &rgSchCmnUlCqiToTbsTbl[RG_SCH_CMN_EXT_CP][0]; + + /* Initaializing new variable added for UL eff */ + rgSchCmnUlEffTbl[RG_SCH_CMN_EXT_CP] = &rgSchCmnExtUlEff[0]; + /* Reason behind using 3 as the number of symbols to rule out for + * efficiency table computation would be that we are using 2 symbols for + * DMRS(1 in each slot) and 1 symbol for SRS*/ + rgSCHCmnCompUlEff(3,RG_SCH_CMN_EXT_CP,rgSchCmnUlEffTbl[RG_SCH_CMN_EXT_CP]); + + for (i = RGSCH_NUM_ITBS - 1, j = RG_SCH_CMN_UL_NUM_CQI - 1; + i >= 0 && j > 0; --i) + { + if ((*effTbl)[i] <= cqiTbl[j].eff) + { + mapTbl[j--] = (U8)i; + } + } + for (; j > 0; --j) + { + mapTbl[j] = 0; + } + rgSCHPwrInit(); + RETVOID; +} + +/** + * @brief This function initializes all the data for the scheduler. + * + * @details + * + * Function: rgSCHCmnInit + * Purpose: This function initializes the following information: + * 1. Efficiency table + * 2. CQI to table index - It is one row for upto 3 RBs + * and another row for greater than 3 RBs + * currently extended prefix is compiled out. + * Invoked by: MAC intialization code..may be ActvInit + * + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnInit +( +) +#else +PUBLIC Void rgSCHCmnInit() +#endif +{ + U8 idx; + TRC2(rgSCHCmnInit); + + rgSCHCmnDlInit(); + rgSCHCmnUlInit(); +#ifdef EMTC_ENABLE + rgSCHEmtcCmnDlInit(); + rgSCHEmtcCmnUlInit(); +#endif +#ifdef LTEMAC_SPS + rgSCHCmnSpsInit(); +#endif + + /* Init the function pointers */ + rgSchCmnApis.rgSCHRgrUeCfg = rgSCHCmnRgrUeCfg; + rgSchCmnApis.rgSCHRgrUeRecfg = rgSCHCmnRgrUeRecfg; + rgSchCmnApis.rgSCHFreeUe = rgSCHCmnUeDel; + rgSchCmnApis.rgSCHRgrCellCfg = rgSCHCmnRgrCellCfg; + rgSchCmnApis.rgSCHRgrCellRecfg = rgSCHCmnRgrCellRecfg; + rgSchCmnApis.rgSCHFreeCell = rgSCHCmnCellDel; + rgSchCmnApis.rgSCHRgrLchCfg = rgSCHCmnRgrLchCfg; + rgSchCmnApis.rgSCHRgrLcgCfg = rgSCHCmnRgrLcgCfg; + rgSchCmnApis.rgSCHRgrLchRecfg = rgSCHCmnRgrLchRecfg; + rgSchCmnApis.rgSCHRgrLcgRecfg = rgSCHCmnRgrLcgRecfg; + rgSchCmnApis.rgSCHFreeDlLc = rgSCHCmnFreeDlLc; + rgSchCmnApis.rgSCHFreeLcg = rgSCHCmnLcgDel; + rgSchCmnApis.rgSCHRgrLchDel = rgSCHCmnRgrLchDel; + rgSchCmnApis.rgSCHActvtUlUe = rgSCHCmnActvtUlUe; + rgSchCmnApis.rgSCHActvtDlUe = rgSCHCmnActvtDlUe; + rgSchCmnApis.rgSCHHdlUlTransInd = rgSCHCmnHdlUlTransInd; + rgSchCmnApis.rgSCHDlDedBoUpd = rgSCHCmnDlDedBoUpd; + rgSchCmnApis.rgSCHUlRecMsg3Alloc = rgSCHCmnUlRecMsg3Alloc; + rgSchCmnApis.rgSCHUlCqiInd = rgSCHCmnUlCqiInd; + rgSchCmnApis.rgSCHPucchDeltaPwrInd = rgSCHPwrPucchDeltaInd; + rgSchCmnApis.rgSCHUlHqProcForUe = rgSCHCmnUlHqProcForUe; +#ifdef RG_UNUSED + rgSchCmnApis.rgSCHUpdUlHqProc = rgSCHCmnUpdUlHqProc; +#endif + rgSchCmnApis.rgSCHUpdBsrShort = rgSCHCmnUpdBsrShort; + rgSchCmnApis.rgSCHUpdBsrTrunc = rgSCHCmnUpdBsrTrunc; + rgSchCmnApis.rgSCHUpdBsrLong = rgSCHCmnUpdBsrLong; + rgSchCmnApis.rgSCHUpdPhr = rgSCHCmnUpdPhr; + rgSchCmnApis.rgSCHUpdExtPhr = rgSCHCmnUpdExtPhr; + rgSchCmnApis.rgSCHContResUlGrant = rgSCHCmnContResUlGrant; + rgSchCmnApis.rgSCHSrRcvd = rgSCHCmnSrRcvd; + rgSchCmnApis.rgSCHFirstRcptnReq = rgSCHCmnFirstRcptnReq; + rgSchCmnApis.rgSCHNextRcptnReq = rgSCHCmnNextRcptnReq; + rgSchCmnApis.rgSCHFirstHqFdbkAlloc = rgSCHCmnFirstHqFdbkAlloc; + rgSchCmnApis.rgSCHNextHqFdbkAlloc = rgSCHCmnNextHqFdbkAlloc; + rgSchCmnApis.rgSCHDlProcAddToRetx = rgSCHCmnDlProcAddToRetx; + rgSchCmnApis.rgSCHDlCqiInd = rgSCHCmnDlCqiInd; +#ifdef EMTC_ENABLE + rgSchCmnApis.rgSCHUlProcAddToRetx = rgSCHCmnEmtcUlProcAddToRetx; +#endif +#ifdef TFU_UPGRADE + rgSchCmnApis.rgSCHSrsInd = rgSCHCmnSrsInd; +#endif + rgSchCmnApis.rgSCHDlTARpt = rgSCHCmnDlTARpt; + rgSchCmnApis.rgSCHDlRlsSubFrm = rgSCHCmnDlRlsSubFrm; + rgSchCmnApis.rgSCHUeReset = rgSCHCmnUeReset; +#ifdef LTEMAC_SPS + rgSchCmnApis.rgSCHHdlCrntiCE = rgSCHCmnHdlCrntiCE; + rgSchCmnApis.rgSCHDlProcAck = rgSCHCmnDlProcAck; + rgSchCmnApis.rgSCHDlRelPdcchFbk = rgSCHCmnDlRelPdcchFbk; + rgSchCmnApis.rgSCHUlSpsRelInd = rgSCHCmnUlSpsRelInd; + rgSchCmnApis.rgSCHUlSpsActInd = rgSCHCmnUlSpsActInd; + rgSchCmnApis.rgSCHUlCrcFailInd = rgSCHCmnUlCrcFailInd; + rgSchCmnApis.rgSCHUlCrcInd = rgSCHCmnUlCrcInd; +#endif + rgSchCmnApis.rgSCHDrxStrtInActvTmrInUl = rgSCHCmnDrxStrtInActvTmrInUl; + rgSchCmnApis.rgSCHUpdUeDataIndLcg = rgSCHCmnUpdUeDataIndLcg; + + for (idx = 0; idx < RGSCH_NUM_SCHEDULERS; ++idx) + { + rgSchUlSchdInits[idx](&rgSchUlSchdTbl[idx]); + rgSchDlSchdInits[idx](&rgSchDlSchdTbl[idx]); + } +#ifdef EMTC_ENABLE + for (idx = 0; idx < RGSCH_NUM_EMTC_SCHEDULERS; ++idx) + { + rgSchEmtcUlSchdInits[idx](&rgSchEmtcUlSchdTbl[idx]); + rgSchEmtcDlSchdInits[idx](&rgSchEmtcDlSchdTbl[idx]); + } +#endif +#if (defined (RG_PHASE2_SCHED) && defined(TFU_UPGRADE)) + for (idx = 0; idx < RGSCH_NUM_DLFS_SCHEDULERS; ++idx) + { + rgSchDlfsSchdInits[idx](&rgSchDlfsSchdTbl[idx]); + } +#endif +#ifdef LTE_ADV + rgSchCmnApis.rgSCHRgrSCellUeCfg = rgSCHCmnRgrSCellUeCfg; + rgSchCmnApis.rgSCHRgrSCellUeDel = rgSCHCmnRgrSCellUeDel; +#endif + RETVOID; +} + + +/** + * @brief This function is a wrapper to call scheduler specific API. + * + * @details + * + * Function: rgSCHCmnDlRlsSubFrm + * Purpose: Releases scheduler Information from DL SubFrm. + * + * Invoked by: DHM + * + * @param[in] RgSchCellCb *cell + * @param[out] CmLteTimingInfo frm + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlRlsSubFrm +( +RgSchCellCb *cell, +CmLteTimingInfo frm +) +#else +PUBLIC Void rgSCHCmnDlRlsSubFrm(cell, frm) +RgSchCellCb *cell; +CmLteTimingInfo frm; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchDlSf *sf; + + TRC2(rgSCHCmnDlRlsSubFrm); + + /* Get the pointer to the subframe */ + sf = rgSCHUtlSubFrmGet(cell, frm); + + rgSCHUtlSubFrmPut(cell, sf); + if (sf->dlfsSf) + { + /* Re-initialize DLFS specific information for the sub-frame */ + cellSch->apisDlfs->rgSCHDlfsReinitSf(cell, sf); + } + RETVOID; +} + + + +/** + * @brief This function is the starting function for DL allocation. + * + * @details + * + * Function: rgSCHCmnDlCmnChAlloc + * Purpose: Scheduling for downlink. It performs allocation in the order + * of priority wich BCCH/PCH first, CCCH, Random Access and TA. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[out] RgSchCmnDlRbAllocInfo* allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchRarAlloc +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnDlCcchRarAlloc(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnDlCcchRarAlloc); + + rgSCHCmnDlCcchRetx(cell, &cellSch->allocInfo); + /* LTE_ADV_FLAG_REMOVED_START */ + if(RG_SCH_ABS_ENABLED_ABS_SF == cell->lteAdvCb.absDlSfInfo) + { + if(cell->lteAdvCb.absCfg.absPatternType & RGR_ABS_MUTE) + { + /*eNodeB need to blank the subframe */ + } + else + { + rgSCHCmnDlCcchTx(cell, &cellSch->allocInfo); + } + } + else + { + rgSCHCmnDlCcchTx(cell, &cellSch->allocInfo); + } + /* LTE_ADV_FLAG_REMOVED_END */ + +#ifdef RGR_V1 + + /*Added these function calls for processing CCCH SDU arriving + * after guard timer expiry.Functions differ from above two functions + * in using ueCb instead of raCb.*/ + rgSCHCmnDlCcchSduRetx(cell, &cellSch->allocInfo); + /* LTE_ADV_FLAG_REMOVED_START */ + if(RG_SCH_ABS_ENABLED_ABS_SF == cell->lteAdvCb.absDlSfInfo) + { + if(cell->lteAdvCb.absCfg.absPatternType & RGR_ABS_MUTE) + { + /*eNodeB need to blank the subframe */ + } + else + { + rgSCHCmnDlCcchSduTx(cell, &cellSch->allocInfo); + } + } + else + { + rgSCHCmnDlCcchSduTx(cell, &cellSch->allocInfo); + } + /* LTE_ADV_FLAG_REMOVED_END */ +#endif + +#ifdef LTE_TDD + if(cellSch->ul.msg3SchdIdx != RGSCH_INVALID_INFO) + { + /* Do not schedule msg3 if there is a CFI change ongoing */ + if (cellSch->dl.currCfi == cellSch->dl.newCfi) + { + rgSCHCmnDlRaRsp(cell, &cellSch->allocInfo); + } + } +#else + /* LTE_ADV_FLAG_REMOVED_START */ + if(RG_SCH_ABS_ENABLED_ABS_SF == cell->lteAdvCb.absDlSfInfo) + { + if(cell->lteAdvCb.absCfg.absPatternType & RGR_ABS_MUTE) + { + /*eNodeB need to blank the subframe */ + } + else + { + /* Do not schedule msg3 if there is a CFI change ongoing */ + if (cellSch->dl.currCfi == cellSch->dl.newCfi) + { + rgSCHCmnDlRaRsp(cell, &cellSch->allocInfo); + } + } + } + else + { + /* Do not schedule msg3 if there is a CFI change ongoing */ + if (cellSch->dl.currCfi == cellSch->dl.newCfi) + { + rgSCHCmnDlRaRsp(cell, &cellSch->allocInfo); + } + } + /* LTE_ADV_FLAG_REMOVED_END */ +#endif + + RETVOID; +} + +#ifdef RGR_V1 +/** + * @brief Scheduling for CCCH SDU. + * + * @details + * + * Function: rgSCHCmnCcchSduAlloc + * Purpose: Scheduling for CCCH SDU + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ueCb + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnCcchSduAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ueCb, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE S16 rgSCHCmnCcchSduAlloc(cell, ueCb, allocInfo) +RgSchCellCb *cell; +RgSchUeCb *ueCb; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchDlRbAlloc *rbAllocInfo; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell); + + TRC2(rgSCHCmnCcchSduAlloc); + + /* Return if subframe BW exhausted */ + if (allocInfo->ccchSduAlloc.ccchSduDlSf->bw <= + allocInfo->ccchSduAlloc.ccchSduDlSf->bwAssigned) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "bw<=bwAssigned for UEID:%d",ueCb->ueId); + RETVALUE(RFAILED); + } + + if (rgSCHDhmGetCcchSduHqProc(ueCb, cellSch->dl.time, &(ueDl->proc)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHDhmGetCcchSduHqProc failed UEID:%d",ueCb->ueId); + RETVALUE(RFAILED); + } + + rbAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ueCb, cell); + rbAllocInfo->dlSf = allocInfo->ccchSduAlloc.ccchSduDlSf; + + if (rgSCHCmnCcchSduDedAlloc(cell, ueCb) != ROK) + { + /* Fix : syed Minor failure handling, release hqP if Unsuccessful */ + rgSCHDhmRlsHqpTb(ueDl->proc, 0, FALSE); + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnCcchSduDedAlloc failed UEID:%d",ueCb->ueId); + RETVALUE(RFAILED); + } + cmLListAdd2Tail(&allocInfo->ccchSduAlloc.ccchSduTxLst, &ueDl->proc->reqLnk); + ueDl->proc->reqLnk.node = (PTR)ueDl->proc; + allocInfo->ccchSduAlloc.ccchSduDlSf->schdCcchUe++; + + RETVALUE(ROK); +} +/** + * @brief This function scheduler for downlink CCCH messages. + * + * @details + * + * Function: rgSCHCmnDlCcchSduTx + * Purpose: Scheduling for downlink CCCH + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchSduTx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchSduTx(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchUeCb *ueCb; + RgSchCmnDlUe *ueCmnDl; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + RgSchDlSf *dlSf = allocInfo->ccchSduAlloc.ccchSduDlSf; + + TRC2(rgSCHCmnDlCcchSduTx); + + node = cell->ccchSduUeLst.first; + while(node) + { + if(cellSch->dl.maxCcchPerDlSf && + dlSf->schdCcchUe == cellSch->dl.maxCcchPerDlSf) + { + break; + } + else + { + ueCb = (RgSchUeCb *)(node->node); + ueCmnDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell); + node = node->next; + /* Fix : syed postpone scheduling for this + * until msg4 is done */ + /* Fix : syed RLC can erroneously send CCCH SDU BO + * twice. Hence an extra guard to avoid if already + * scheduled for RETX */ + if ((!(ueCb->dl.dlInactvMask & RG_HQENT_INACTIVE)) && + (!ueCmnDl->proc)) + { + if ((rgSCHCmnCcchSduAlloc(cell, ueCb, allocInfo)) != ROK) + { + break; + } + } + else + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"ERROR!! THIS SHOULD " + "NEVER HAPPEN for UEID:%d", ueCb->ueId); + continue; + } + } + } + RETVOID; +} +#endif + +/** + * @brief This function scheduler for downlink CCCH messages. + * + * @details + * + * Function: rgSCHCmnDlCcchTx + * Purpose: Scheduling for downlink CCCH + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchTx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchTx(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchRaCb *raCb; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchDlSf *dlSf = allocInfo->msg4Alloc.msg4DlSf; + + TRC2(rgSCHCmnDlCcchTx); + + node = cell->raInfo.toBeSchdLst.first; + while(node) + { + if(cellSch->dl.maxCcchPerDlSf && + dlSf->schdCcchUe == cellSch->dl.maxCcchPerDlSf) + { + break; + } + else + { + + raCb = (RgSchRaCb *)(node->node); + node = node->next; + /* Address allocation for this UE for MSG 4 */ + /* Allocation for Msg4 */ + if ((rgSCHCmnMsg4Alloc(cell, raCb, allocInfo)) != ROK) + { + break; + } + } + } + RETVOID; +} + +#ifdef RGR_V1 +/** + * @brief This function scheduler for downlink CCCH messages. + * + * @details + * + * Function: rgSCHCmnDlCcchSduRetx + * Purpose: Scheduling for downlink CCCH + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchSduRetx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchSduRetx(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchDlRbAlloc *rbAllocInfo; + CmLList *node; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchUeCb *ueCb; + RgSchDlHqProcCb *hqP; + U8 retxBw = 0; + RgSchCmnDlUe *ueDl; + RgSchDlSf *dlSf = allocInfo->ccchSduAlloc.ccchSduDlSf; + + TRC2(rgSCHCmnDlCcchSduRetx); + + node = cellSch->dl.ccchSduRetxLst.first; + while(node) + { + if(cellSch->dl.maxCcchPerDlSf && + dlSf->schdCcchUe == cellSch->dl.maxCcchPerDlSf) + { + break; + } + else + { + + hqP = (RgSchDlHqProcCb *)(node->node); + node = node->next; + + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if (rgSCHCmnRetxAvoidTdd(allocInfo->ccchSduAlloc.ccchSduDlSf, + cell, hqP) == TRUE) + { + continue; + } +#endif + /* DwPts Scheduling Changes End */ + + if (hqP->tbInfo[0].dlGrnt.numRb > (dlSf->bw - dlSf->bwAssigned)) + { + break; + } + ueCb = (RgSchUeCb*)(hqP->hqE->ue); + ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell); + + rbAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ueCb, cell); + /* Fill RB Alloc Info */ + rbAllocInfo->dlSf = dlSf; + rbAllocInfo->tbInfo[0].bytesReq = hqP->tbInfo[0].ccchSchdInfo.totBytes; + rbAllocInfo->rbsReq = hqP->tbInfo[0].dlGrnt.numRb; + /* Fix : syed iMcs setting did not correspond to RETX */ + RG_SCH_CMN_GET_MCS_FOR_RETX((&hqP->tbInfo[0]), + rbAllocInfo->tbInfo[0].imcs); + rbAllocInfo->rnti = ueCb->ueId; + rbAllocInfo->tbInfo[0].noLyr = hqP->tbInfo[0].numLyrs; + /* Fix : syed Copying info in entirety without depending on stale TX information */ + rbAllocInfo->tbInfo[0].tbCb = &hqP->tbInfo[0]; + rbAllocInfo->tbInfo[0].schdlngForTb = TRUE; + /* Fix : syed Assigning proc to scratchpad */ + ueDl->proc = hqP; + + retxBw += rbAllocInfo->rbsReq; + + cmLListAdd2Tail(&allocInfo->ccchSduAlloc.ccchSduRetxLst, \ + &hqP->reqLnk); + hqP->reqLnk.node = (PTR)hqP; + dlSf->schdCcchUe++; + } + } + dlSf->bwAssigned += retxBw; + RETVOID; +} +#endif + +/** + * @brief This function scheduler for downlink CCCH messages. + * + * @details + * + * Function: rgSCHCmnDlCcchRetx + * Purpose: Scheduling for downlink CCCH + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchRetx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchRetx(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchRaCb *raCb; + RgSchDlHqProcCb *hqP; + U8 retxBw = 0; + RgSchDlSf *dlSf = allocInfo->msg4Alloc.msg4DlSf; + + TRC2(rgSCHCmnDlCcchRetx); + + node = cellSch->dl.msg4RetxLst.first; + while(node) + { + if(cellSch->dl.maxCcchPerDlSf && + dlSf->schdCcchUe == cellSch->dl.maxCcchPerDlSf) + { + break; + } + else + { + hqP = (RgSchDlHqProcCb *)(node->node); + + node = node->next; + + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if (rgSCHCmnRetxAvoidTdd(allocInfo->msg4Alloc.msg4DlSf, + cell, hqP) == TRUE) + { + continue; + } +#endif + /* DwPts Scheduling Changes End */ + + if (hqP->tbInfo[0].dlGrnt.numRb > (dlSf->bw - dlSf->bwAssigned)) + { + break; + } + raCb = (RgSchRaCb*)(hqP->hqE->raCb); + /* Fill RB Alloc Info */ + raCb->rbAllocInfo.dlSf = dlSf; + raCb->rbAllocInfo.tbInfo[0].bytesReq = hqP->tbInfo[0].ccchSchdInfo.totBytes; + raCb->rbAllocInfo.rbsReq = hqP->tbInfo[0].dlGrnt.numRb; + /* Fix : syed iMcs setting did not correspond to RETX */ + RG_SCH_CMN_GET_MCS_FOR_RETX((&hqP->tbInfo[0]), + raCb->rbAllocInfo.tbInfo[0].imcs); + raCb->rbAllocInfo.rnti = raCb->tmpCrnti; + raCb->rbAllocInfo.tbInfo[0].noLyr = hqP->tbInfo[0].numLyrs; + /* Fix; syed Copying info in entirety without depending on stale TX information */ + raCb->rbAllocInfo.tbInfo[0].tbCb = &hqP->tbInfo[0]; + raCb->rbAllocInfo.tbInfo[0].schdlngForTb = TRUE; + + retxBw += raCb->rbAllocInfo.rbsReq; + + cmLListAdd2Tail(&allocInfo->msg4Alloc.msg4RetxLst, \ + &hqP->reqLnk); + hqP->reqLnk.node = (PTR)hqP; + dlSf->schdCcchUe++; + } + } + dlSf->bwAssigned += retxBw; + RETVOID; +} + + +/** + * @brief This function implements scheduler DL allocation for + * for broadcast (on PDSCH) and paging. + * + * @details + * + * Function: rgSCHCmnDlBcchPcch + * Purpose: This function implements scheduler for DL allocation + * for broadcast (on PDSCH) and paging. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlBcchPcch +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgInfSfAlloc *subfrmAlloc +) +#else +PRIVATE Void rgSCHCmnDlBcchPcch(cell, allocInfo, subfrmAlloc) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +RgInfSfAlloc *subfrmAlloc; +#endif +{ + CmLteTimingInfo frm; + RgSchDlSf *sf; + RgSchClcDlLcCb *pcch; + RgSchClcBoRpt *bo; +#ifndef RGR_SI_SCH + Bool valid; + RgSchClcDlLcCb *bcch, *bch; +#endif/*RGR_SI_SCH*/ + + + TRC2(rgSCHCmnDlBcchPcch); + + frm = cell->crntTime; +#ifdef LTEMAC_HDFDD + /* For HDFDD we need scheduling information at least RG_SCH_CMN_DL_DELTA + + RG_SCH_CMN_HARQ_INTERVAL (7) subframes ahead */ + RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL); +#else + RGSCH_SUBFRAME_INDEX(frm); + //RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA); +#endif + + /* Compute the subframe for which allocation is being made */ + /* essentially, we need pointer to the dl frame for this subframe */ + sf = rgSCHUtlSubFrmGet(cell, frm); + + +#ifndef RGR_SI_SCH + bch = rgSCHDbmGetBcchOnBch(cell); +#if (ERRCLASS & ERRCLS_DEBUG) + if (bch == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"BCCH on BCH is not configured"); + RETVOID; + } +#endif + if (bch->boLst.first != NULLP) + { + bo = (RgSchClcBoRpt *)(bch->boLst.first->node); + if (RGSCH_TIMEINFO_SAME(frm, bo->timeToTx)) + { + sf->bch.tbSize = bo->bo; + cmLListDelFrm(&bch->boLst, bch->boLst.first); + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&bo, sizeof(*bo)); + rgSCHUtlFillRgInfCmnLcInfo(sf, subfrmAlloc, bch->lcId,TRUE); + } + } + else + { + if ((frm.sfn % 4 == 0) && (frm.subframe == 0)) + { + } + } + + allocInfo->bcchAlloc.schdFirst = FALSE; + bcch = rgSCHDbmGetFirstBcchOnDlsch(cell); +#if (ERRCLASS & ERRCLS_DEBUG) + if (bcch == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"BCCH on DLSCH is not configured"); + RETVOID; + } +#endif + if (bcch->boLst.first != NULLP) + { + bo = (RgSchClcBoRpt *)(bcch->boLst.first->node); + + if (RGSCH_TIMEINFO_SAME(frm, bo->timeToTx)) + { + allocInfo->bcchAlloc.schdFirst = TRUE; + /* Time to perform allocation for this BCCH transmission */ + rgSCHCmnClcAlloc(cell, sf, bcch, RGSCH_SI_RNTI, allocInfo); + } + } + + if(!allocInfo->bcchAlloc.schdFirst) + { + CmLList *lnk; + bcch = rgSCHDbmGetSecondBcchOnDlsch(cell); +#if (ERRCLASS & ERRCLS_DEBUG) + if (bcch == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"BCCH on DLSCH is not configured"); + RETVOID; + } +#endif + lnk = bcch->boLst.first; + while (lnk != NULLP) + { + bo = (RgSchClcBoRpt *)(lnk->node); + lnk = lnk->next; + valid = rgSCHCmnChkInWin(frm, bo->timeToTx, bo->maxTimeToTx); + + if(valid) + { + bo->i = RGSCH_CALC_SF_DIFF(frm, bo->timeToTx); + /* Time to perform allocation for this BCCH transmission */ + rgSCHCmnClcAlloc(cell, sf, bcch, RGSCH_SI_RNTI, allocInfo); + break; + } + else + { + valid = rgSCHCmnChkPastWin(frm, bo->maxTimeToTx); + if(valid) + { + cmLListDelFrm(&bcch->boLst, &bo->boLstEnt); + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&bo, + sizeof(RgSchClcBoRpt)); + } + } + } + } +#else + rgSCHDlSiSched(cell, allocInfo, subfrmAlloc); +#endif/*RGR_SI_SCH*/ + + pcch = rgSCHDbmGetPcch(cell); +#ifdef ERRCLS_KW + if (pcch == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"PCCH on DLSCH is not configured"); + RETVOID; + } +#endif + if (pcch->boLst.first != NULLP) + { + bo = (RgSchClcBoRpt *)(pcch->boLst.first->node); + + if (RGSCH_TIMEINFO_SAME(frm, bo->timeToTx)) + { + /* Time to perform allocation for this PCCH transmission */ + rgSCHCmnClcAlloc(cell, sf, pcch, RGSCH_P_RNTI, allocInfo); + } + } + RETVOID; +} + +/* +* +* Fun: rgSCHCmnChkInWin +* +* Desc: This function checks if frm occurs in window +* +* Ret: TRUE - if in window +* FALSE - otherwise +* +* Notes: None +* +* File: rg_sch_cmn.c +* +*/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnChkInWin +( +CmLteTimingInfo frm, +CmLteTimingInfo start, +CmLteTimingInfo end +) +#else +PUBLIC Bool rgSCHCmnChkInWin(frm, start, end) +CmLteTimingInfo frm; +CmLteTimingInfo start; +CmLteTimingInfo end; +#endif +{ + Bool inWin = FALSE; + + TRC2(rgSCHCmnChkInWin); + + if (end.sfn > start.sfn) + { + if (frm.sfn > start.sfn + || (frm.sfn == start.sfn && frm.subframe >= start.subframe)) + { + if (frm.sfn < end.sfn +#ifdef EMTC_ENABLE + || (frm.sfn == end.sfn && frm.subframe <= end.subframe)) +#else + || (frm.sfn == end.sfn && frm.subframe <= start.subframe)) +#endif + { + inWin = TRUE; + } + } + } + /* Testing for wrap around, sfn wraparound check should be enough */ + else if (end.sfn < start.sfn) + { + if (frm.sfn > start.sfn + || (frm.sfn == start.sfn && frm.subframe >= start.subframe)) + { + inWin = TRUE; + } + else + { + if (frm.sfn < end.sfn + || (frm.sfn == end.sfn && frm.subframe <= end.subframe)) + { + inWin = TRUE; + } + } + } + else /* start.sfn == end.sfn */ + { + if (frm.sfn == start.sfn + && (frm.subframe >= start.subframe + && frm.subframe <= end.subframe)) + { + inWin = TRUE; + } + } + + RETVALUE(inWin); +} /* end of rgSCHCmnChkInWin*/ + +/* +* +* Fun: rgSCHCmnChkPastWin +* +* Desc: This function checks if frm has gone past window edge +* +* Ret: TRUE - if past window edge +* FALSE - otherwise +* +* Notes: None +* +* File: rg_sch_cmn.c +* +*/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnChkPastWin +( +CmLteTimingInfo frm, +CmLteTimingInfo end +) +#else +PUBLIC Bool rgSCHCmnChkPastWin(frm, end) +CmLteTimingInfo frm; +CmLteTimingInfo end; +#endif +{ + CmLteTimingInfo refFrm = end; + Bool pastWin; + + TRC2(rgSCHCmnChkPastWin); + + RGSCH_INCR_FRAME(refFrm.sfn); + RGSCH_INCR_SUB_FRAME(end, 1); + pastWin = rgSCHCmnChkInWin(frm, end, refFrm); + + RETVALUE(pastWin); +} /* end of rgSCHCmnChkPastWin*/ + +/** + * @brief This function implements allocation of the resources for common + * channels BCCH, PCCH. + * + * @details + * + * Function: rgSCHCmnClcAlloc + * Purpose: This function implements selection of number of RBs based + * the allowed grant for the service. It is also responsible + * for selection of MCS for the transmission. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell, + * @param[in] RgSchDlSf *sf, + * @param[in] RgSchClcDlLcCb *lch, + * @param[in] U16 rnti, + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnClcAlloc +( +RgSchCellCb *cell, +RgSchDlSf *sf, +RgSchClcDlLcCb *lch, +U16 rnti, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnClcAlloc(cell, sf, lch, rnti, allocInfo) +RgSchCellCb *cell; +RgSchDlSf *sf; +RgSchClcDlLcCb *lch; +U16 rnti; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchClcBoRpt *bo; + U32 rb=0; + U8 mcs; + U32 tbs; +#ifdef LTE_TDD + U8 lostRe; + U8 cfi = cellDl->currCfi; +#endif + + TRC2(rgSCHCmnClcAlloc); + + bo = (RgSchClcBoRpt *)(lch->boLst.first->node); + + mcs = bo->mcs; + tbs = bo->bo; + /* rgSCHCmnClcRbAllocForFxdTb(cell, bo->bo, cellDl->ccchCqi, &rb);*/ + if(cellDl->bitsPerRb==0) + { + while ((rgTbSzTbl[0][0][rb]) < (tbs*8)) + { + rb++; + } + rb = rb+1; + } + else + { + rb = RGSCH_CEIL((tbs*8), cellDl->bitsPerRb); + } + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + if(sf->sfType == RG_SCH_SPL_SF_DATA) + { + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, cfi); + + /* Calculate the less RE's because of DwPTS */ + lostRe = rb * (cellDl->noResPerRb[cfi] - cellDl->numReDwPts[cfi]); + + /* Increase number of RBs in Spl SF to compensate for lost REs */ + rb += RGSCH_CEIL(lostRe, cellDl->numReDwPts[cfi]); + } +#endif + /* DwPTS Scheduling Changes End */ + /*ccpu00115595- end*/ + /* additional check to see if required RBs + * exceeds the available */ + if (rb > sf->bw - sf->bwAssigned) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"BW allocation " + "failed for CRNTI:%d",rnti); + RETVOID; + } + + /* Update the subframe Allocated BW field */ + sf->bwAssigned = sf->bwAssigned + rb; + /* Fill in the BCCH/PCCH transmission info to the RBAllocInfo struct */ + if (rnti == RGSCH_SI_RNTI) + { + allocInfo->bcchAlloc.rnti = rnti; + allocInfo->bcchAlloc.dlSf = sf; + allocInfo->bcchAlloc.tbInfo[0].bytesReq = tbs; + allocInfo->bcchAlloc.rbsReq = rb; + allocInfo->bcchAlloc.tbInfo[0].imcs = mcs; + allocInfo->bcchAlloc.tbInfo[0].noLyr = 1; + /* Nprb indication at PHY for common Ch */ + allocInfo->bcchAlloc.nPrb = bo->nPrb; + } + else + { + allocInfo->pcchAlloc.rnti = rnti; + allocInfo->pcchAlloc.dlSf = sf; + allocInfo->pcchAlloc.tbInfo[0].bytesReq = tbs; + allocInfo->pcchAlloc.rbsReq = rb; + allocInfo->pcchAlloc.tbInfo[0].imcs = mcs; + allocInfo->pcchAlloc.tbInfo[0].noLyr = 1; + allocInfo->pcchAlloc.nPrb = bo->nPrb; + } + RETVOID; +} + + +/** + * @brief This function implements PDCCH allocation for common channels. + * + * @details + * + * Function: rgSCHCmnCmnPdcchAlloc + * Purpose: This function implements allocation of PDCCH for a UE. + * 1. This uses index 0 of PDCCH table for efficiency. + * 2. Uses he candidate PDCCH count for the aggr level. + * 3. Look for availability for each candidate and choose + * the first one available. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *sf + * @return RgSchPdcch * + * -# NULLP when unsuccessful + * + **/ +#ifdef ANSI +PUBLIC RgSchPdcch *rgSCHCmnCmnPdcchAlloc +( +RgSchCellCb *cell, +RgSchDlSf *subFrm +) +#else +PUBLIC RgSchPdcch *rgSCHCmnCmnPdcchAlloc(cell, subFrm) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +#endif +{ + CmLteAggrLvl aggrLvl; + RgSchPdcchInfo *pdcchInfo; + RgSchPdcch *pdcch; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 numCce; /*store num CCEs based on + aggregation level */ + TRC2(rgSCHCmnCmnPdcchAlloc); + + aggrLvl = cellSch->dl.cmnChAggrLvl; + + pdcchInfo = &(subFrm->pdcchInfo); + + /* Updating the no. of nCce in pdcchInfo, in case if CFI + * was changed */ +#ifdef LTE_TDD + if(subFrm->nCce != pdcchInfo->nCce) + { + rgSCHUtlPdcchInit(cell, subFrm, subFrm->nCce); + } +#else + if(cell->nCce != pdcchInfo->nCce) + { + rgSCHUtlPdcchInit(cell, subFrm, cell->nCce); + } +#endif + + switch (aggrLvl) + { + case CM_LTE_AGGR_LVL4: + numCce = 4; + break; + case CM_LTE_AGGR_LVL8: + numCce = 8; + break; + case CM_LTE_AGGR_LVL16: + numCce = 16; + break; + default: + RETVALUE(NULLP); + } + + if (rgSCHUtlPdcchAvail(cell, pdcchInfo, aggrLvl, &pdcch) == TRUE) + { +#ifdef LTEMAC_SPS + pdcch->isSpsRnti = FALSE; +#endif + /* Increment the CCE used counter in the current subframe */ + subFrm->cceCnt += numCce; + pdcch->pdcchSearchSpace = RG_SCH_CMN_SEARCH_SPACE; + + RETVALUE(pdcch); + } + + /* PDCCH Allocation Failed, Mark cceFailure flag as TRUE */ + subFrm->isCceFailure = TRUE; + + RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId, + "PDCCH ERR: NO PDDCH AVAIL IN COMMON SEARCH SPACE aggr:%u", + aggrLvl); + RETVALUE(NULLP); +} + + +/** + * @brief This function implements bandwidth allocation for common channels. + * + * @details + * + * Function: rgSCHCmnClcRbAlloc + * Purpose: This function implements bandwith allocation logic + * for common control channels. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] U32 bo + * @param[in] U8 cqi + * @param[in] U8 *rb + * @param[in] U32 *tbs + * @param[in] U8 *mcs + * @param[in] RgSchDlSf *sf + * @return Void + * + **/ +#ifdef LTEMAC_SPS +#ifdef ANSI +PUBLIC Void rgSCHCmnClcRbAlloc +( +RgSchCellCb *cell, +U32 bo, +U8 cqi, +U8 *rb, +U32 *tbs, +U8 *mcs, +U8 *iTbs, +Bool isSpsBo, +RgSchDlSf *sf +) +#else +PUBLIC Void rgSCHCmnClcRbAlloc(cell, bo, cqi, rb, tbs, mcs, iTbs, isSpsBo) +RgSchCellCb *cell; +U32 bo; +U8 cqi; +U8 *rb; +U32 *tbs; +U8 *mcs; +U8 *iTbs; +Bool isSpsBo; +RgSchDlSf *sf; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSCHCmnClcRbAlloc +( +RgSchCellCb *cell, +U32 bo, +U8 cqi, +U8 *rb, +U32 *tbs, +U8 *mcs, +RgSchDlSf *sf +) +#else +PRIVATE Void rgSCHCmnClcRbAlloc(cell, bo, cqi, rb, tbs, mcs, sf) +RgSchCellCb *cell; +U32 bo; +U8 cqi; +U8 *rb; +U32 *tbs; +U8 *mcs; +RgSchDlSf *sf; +#endif +#endif /* LTEMAC_SPS */ +{ + U8 iTbsVal; + RgSchCmnTbSzEff *effTbl; + U32 eff; + U32 noRes; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 cfi = cellSch->dl.currCfi; + U32 tmpRb=0; + TRC2(rgSCHCmnClcRbAlloc); + + /* first get the CQI to MCS table and determine the number of RBs */ + effTbl = (RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]); + iTbsVal = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[cqi]; + RG_SCH_CMN_DL_TBS_TO_MCS(iTbsVal, *mcs); + + /* Efficiency is number of bits per 1024 REs */ + eff = (*effTbl)[iTbsVal]; + + /* Get the number of REs needed for this bo */ + noRes = ((bo * 8 * 1024) / eff ); + + /* Get the number of RBs needed for this transmission */ + /* Number of RBs = No of REs / No of REs per RB */ + tmpRb = RGSCH_CEIL(noRes, cellSch->dl.noResPerRb[cfi]); + /* KWORK_FIX: added check to see if rb has crossed maxRb*/ + RGSCH_ARRAY_BOUND_CHECK_WITH_POS_IDX(cell->instIdx, rgTbSzTbl[0][0], (tmpRb-1)); + if (tmpRb > cellSch->dl.maxDlBwPerUe) + { + tmpRb = cellSch->dl.maxDlBwPerUe; + } + while ((rgTbSzTbl[0][iTbsVal][tmpRb-1]/8) < bo && + (tmpRb < cellSch->dl.maxDlBwPerUe)) + { + tmpRb++; + RGSCH_ARRAY_BOUND_CHECK_WITH_POS_IDX(cell->instIdx, rgTbSzTbl[0][0], (tmpRb-1)); + } + *tbs = rgTbSzTbl[0][iTbsVal][tmpRb-1]/8; + *rb = (U8)tmpRb; + RG_SCH_CMN_DL_TBS_TO_MCS(iTbsVal, *mcs); + + RETVOID; +} + + + +/** + * @brief Scheduling for MSG4. + * + * @details + * + * Function: rgSCHCmnMsg4Alloc + * Purpose: Scheduling for MSG4 + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchRaCb* raCb + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnMsg4Alloc +( +RgSchCellCb *cell, +RgSchRaCb *raCb, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE S16 rgSCHCmnMsg4Alloc(cell, raCb, allocInfo) +RgSchCellCb *cell; +RgSchRaCb *raCb; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnMsg4Alloc); + + /* SR_RACH_STATS : MSG4 TO BE TXED */ + rgNumMsg4ToBeTx++; + /* Return if subframe BW exhausted */ + if (allocInfo->msg4Alloc.msg4DlSf->bw <= + allocInfo->msg4Alloc.msg4DlSf->bwAssigned) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId , + "bw<=bwAssigned"); + RETVALUE(RFAILED); + } + + if (rgSCHDhmGetMsg4HqProc(raCb, cellSch->dl.time) != ROK) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHDhmGetMsg4HqProc failed"); + RETVALUE(RFAILED); + } + + raCb->rbAllocInfo.dlSf = allocInfo->msg4Alloc.msg4DlSf; + + if (rgSCHCmnMsg4DedAlloc(cell, raCb) != ROK) + { + /* Fix : syed Minor failure handling, release hqP if Unsuccessful */ + rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, FALSE); + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnMsg4DedAlloc failed."); + RETVALUE(RFAILED); + } + cmLListAdd2Tail(&allocInfo->msg4Alloc.msg4TxLst, &raCb->dlHqE->msg4Proc->reqLnk); + raCb->dlHqE->msg4Proc->reqLnk.node = (PTR)raCb->dlHqE->msg4Proc; + allocInfo->msg4Alloc.msg4DlSf->schdCcchUe++; + + RETVALUE(ROK); +} + + +/** + * @brief This function implements PDCCH allocation for an UE. + * + * @details + * + * Function: PdcchAlloc + * Purpose: This function implements allocation of PDCCH for an UE. + * 1. Get the aggregation level for the CQI of the UE. + * 2. Get the candidate PDCCH count for the aggr level. + * 3. Look for availability for each candidate and choose + * the first one available. + * + * Invoked by: Scheduler + * + * @param[in] cell + * @param[in] subFrm + * @param[in] cqi + * @param[in] dciFrmt + * @return RgSchPdcch * + * -# NULLP when unsuccessful + * + **/ +#ifdef ANSI +PUBLIC RgSchPdcch *rgSCHCmnPdcchAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *subFrm, +U8 cqi, +TfuDciFormat dciFrmt, +Bool isDtx +) +#else +PUBLIC RgSchPdcch *rgSCHCmnPdcchAlloc(cell, subFrm, cqi, dciFrmt, isDtx) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlSf *subFrm; +U8 cqi; +TfuDciFormat dciFrmt; +Bool isDtx; +#endif +{ + CmLteAggrLvl aggrLvl; + RgSchPdcchInfo *pdcchInfo; + RgSchPdcch *pdcch; + + TRC2(rgSCHCmnPdcchAlloc); + + /* 3.1 consider the selected DCI format size in determining the + * aggregation level */ + //TODO_SID Need to update. Currently using 4 aggregation level + aggrLvl = CM_LTE_AGGR_LVL2;//cellSch->dciAggrLvl[cqi][dciFrmt]; + +#ifdef LTE_ADV + if((dciFrmt == TFU_DCI_FORMAT_1A) && + ((ue) && (ue->allocCmnUlPdcch)) ) + { + pdcch = rgSCHCmnCmnPdcchAlloc(cell, subFrm); + /* Since CRNTI Scrambled */ + if(NULLP != pdcch) + { + pdcch->dciNumOfBits = ue->dciSize.cmnSize[dciFrmt]; + // prc_trace_format_string(PRC_TRACE_GROUP_PS, PRC_TRACE_INFO_LOW,"Forcing alloc in CMN search spc size %d fmt %d \n", + // pdcch->dciNumOfBits, dciFrmt); + } + RETVALUE(pdcch); + } +#endif + + /* Incrementing aggrLvl by 1 if it not AGGR_LVL8(MAX SIZE) + * inorder to increse the redudancy bits for better decoding of UE */ + if (isDtx) + { + if (aggrLvl != CM_LTE_AGGR_LVL16) + { + switch(aggrLvl) + { + case CM_LTE_AGGR_LVL2: + aggrLvl = CM_LTE_AGGR_LVL4; + break; + case CM_LTE_AGGR_LVL4: + aggrLvl = CM_LTE_AGGR_LVL8; + break; + case CM_LTE_AGGR_LVL8: + aggrLvl = CM_LTE_AGGR_LVL16; + break; + default: + break; + } + /* aggrLvl += 1; */ + } + } + + pdcchInfo = &subFrm->pdcchInfo; + + /* Updating the no. of nCce in pdcchInfo, in case if CFI + * was changed */ +#ifdef LTE_TDD + if(subFrm->nCce != pdcchInfo->nCce) + { + rgSCHUtlPdcchInit(cell, subFrm, subFrm->nCce); + } +#else + if(cell->nCce != pdcchInfo->nCce) + { + rgSCHUtlPdcchInit(cell, subFrm, cell->nCce); + } +#endif + + if (pdcchInfo->nCce < (1 << (aggrLvl - 1))) + { + /* PDCCH Allocation Failed, Mark cceFailure flag as TRUE */ + subFrm->isCceFailure = TRUE; + RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId, + "PDCCH ERR: NO PDDCH AVAIL IN UE SEARCH SPACE :aggr(%u)", + aggrLvl); + + RETVALUE(NULLP); + } + + if (rgSCHUtlPdcchAvail(cell, pdcchInfo, aggrLvl, &pdcch) == TRUE) + { + /* SR_RACH_STATS : Reset isTBMsg4 */ + pdcch->dci.u.format1aInfo.t.pdschInfo.isTBMsg4= FALSE; + pdcch->dci.u.format0Info.isSrGrant = FALSE; +#ifdef LTEMAC_SPS + pdcch->isSpsRnti = FALSE; +#endif + /* Increment the CCE used counter in the current subframe */ + subFrm->cceCnt += aggrLvl; + pdcch->pdcchSearchSpace = RG_SCH_UE_SPECIFIC_SEARCH_SPACE; + if (ue != NULLP) + { +#ifdef LTE_ADV + if (ue->cell != cell) + { + /* Secondary Cell */ + //pdcch->dciNumOfBits = ue->dciSize.noUlCcSize[dciFrmt]; + pdcch->dciNumOfBits = MAX_5GTF_DCIA1B1_SIZE; + } + else +#endif + { + //pdcch->dciNumOfBits = ue->dciSize.dedSize[dciFrmt]; + //TODO_SID Need to update dci size. + pdcch->dciNumOfBits = MAX_5GTF_DCIA1B1_SIZE; + } + } + else + { + /* MSG4 */ + pdcch->dciNumOfBits = cell->dciSize.size[dciFrmt]; + } + RETVALUE(pdcch); + } + + /* PDCCH Allocation Failed, Mark cceFailure flag as TRUE */ + subFrm->isCceFailure = TRUE; + + RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId, + "PDCCH ERR: NO PDDCH AVAIL IN UE SEARCH SPACE :aggr(%u)", + aggrLvl); + RETVALUE(NULLP); +} + +#ifdef RGR_V1 +/** + * @brief This function implements BW allocation for CCCH SDU + * + * @details + * + * Function: rgSCHCmnCcchSduDedAlloc + * Purpose: Downlink bandwidth Allocation for CCCH SDU. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[out] RgSchUeCb *ueCb + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnCcchSduDedAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ueCb +) +#else +PRIVATE S16 rgSCHCmnCcchSduDedAlloc(cell, ueCb) +RgSchCellCb *cell; +RgSchUeCb *ueCb; +#endif +{ + RgSchDlHqEnt *hqE = NULLP; + U32 effBo; + RgSchDlRbAlloc *rbAllocinfo = NULLP; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 iTbs; + U8 numRb; +#ifdef LTE_TDD + U8 cfi = cellDl->currCfi; +#endif + + TRC2(rgSCHCmnCcchSduDedAlloc); + + rbAllocinfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ueCb, cell); + + effBo = ueCb->dlCcchInfo.bo + RGSCH_CCCH_SDU_HDRSIZE; + +#ifndef LTEMAC_SPS + rgSCHCmnClcRbAlloc(cell, effBo, cellDl->ccchCqi, &rbAllocinfo->rbsReq, \ + &rbAllocinfo->tbInfo[0].bytesReq, + &rbAllocinfo->tbInfo[0].imcs, rbAllocinfo->dlSf); +#else /* LTEMAC_SPS */ + rgSCHCmnClcRbAlloc(cell, effBo, cellDl->ccchCqi, &rbAllocinfo->rbsReq, \ + &rbAllocinfo->tbInfo[0].bytesReq,\ + &rbAllocinfo->tbInfo[0].imcs, &iTbs, FALSE, + rbAllocinfo->dlSf); +#endif /* LTEMAC_SPS */ + + iTbs = 0; + /* Cannot exceed the total number of RBs in the cell */ + if ((S16)rbAllocinfo->rbsReq > ((S16)(rbAllocinfo->dlSf->bw - \ + rbAllocinfo->dlSf->bwAssigned))) + { + /* Check if atleast one allocation was possible. + This may be the case where the Bw is very less and + with the configured CCCH CQI, CCCH SDU exceeds the min Bw */ + if (rbAllocinfo->dlSf->bwAssigned == 0) + { + numRb = rbAllocinfo->dlSf->bw; + RG_SCH_CMN_DL_MCS_TO_TBS(rbAllocinfo->tbInfo[0].imcs, iTbs); + while (rgTbSzTbl[0][++iTbs][numRb-1]/8 < effBo) + { + iTbs++; + } + rbAllocinfo->rbsReq = numRb; + rbAllocinfo->tbInfo[0].bytesReq = rgTbSzTbl[0][iTbs][numRb-1]/8; + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + if(rbAllocinfo->dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + rbAllocinfo->tbInfo[0].bytesReq = + rgSCHCmnCalcDwPtsTbSz(cell, effBo, &numRb, &iTbs, 1,cfi); + } +#endif + /* DwPTS Scheduling Changes End */ + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, rbAllocinfo->tbInfo[0].imcs); + } + else + { + RETVALUE(RFAILED); + } + } + + /* Update the subframe Allocated BW field */ + rbAllocinfo->dlSf->bwAssigned = rbAllocinfo->dlSf->bwAssigned + \ + rbAllocinfo->rbsReq; + hqE = RG_SCH_CMN_GET_UE_HQE(ueCb, cell); + rbAllocinfo->tbInfo[0].tbCb = &hqE->ccchSduProc->tbInfo[0]; + rbAllocinfo->rnti = ueCb->ueId; + rbAllocinfo->tbInfo[0].noLyr = 1; + + RETVALUE(ROK); +} +#endif + +/** + * @brief This function implements BW allocation for MSG4 + * + * @details + * + * Function: rgSCHCmnMsg4DedAlloc + * Purpose: Downlink bandwidth Allocation for MSG4. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[out] RgSchRaCb *raCb + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnMsg4DedAlloc +( +RgSchCellCb *cell, +RgSchRaCb *raCb +) +#else +PRIVATE S16 rgSCHCmnMsg4DedAlloc(cell, raCb) +RgSchCellCb *cell; +RgSchRaCb *raCb; +#endif +{ + U32 effBo; + RgSchDlRbAlloc *rbAllocinfo = &raCb->rbAllocInfo; + U8 iTbs; + U8 numRb; +#ifdef LTE_TDD + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 cfi = cellDl->currCfi; +#endif + + TRC2(rgSCHCmnMsg4DedAlloc); + + effBo = raCb->dlCcchInfo.bo + RGSCH_MSG4_HDRSIZE + RGSCH_CONT_RESID_SIZE; + +#ifndef LTEMAC_SPS + rgSCHCmnClcRbAlloc(cell, effBo, raCb->ccchCqi, &rbAllocinfo->rbsReq, \ + &rbAllocinfo->tbInfo[0].bytesReq,\ + &rbAllocinfo->tbInfo[0].imcs, rbAllocinfo->dlSf); +#else /* LTEMAC_SPS */ + rgSCHCmnClcRbAlloc(cell, effBo, raCb->ccchCqi, &rbAllocinfo->rbsReq, \ + &rbAllocinfo->tbInfo[0].bytesReq,\ + &rbAllocinfo->tbInfo[0].imcs, &iTbs, FALSE, + rbAllocinfo->dlSf); +#endif /* LTEMAC_SPS */ + + iTbs = 0; + /* Cannot exceed the total number of RBs in the cell */ + if ((S16)rbAllocinfo->rbsReq > ((S16)(rbAllocinfo->dlSf->bw - \ + rbAllocinfo->dlSf->bwAssigned))) + { + /* Check if atleast one allocation was possible. + This may be the case where the Bw is very less and + with the configured CCCH CQI, CCCH SDU exceeds the min Bw */ + if (rbAllocinfo->dlSf->bwAssigned == 0) + { + numRb = rbAllocinfo->dlSf->bw; + RG_SCH_CMN_DL_MCS_TO_TBS(rbAllocinfo->tbInfo[0].imcs, iTbs); + while (rgTbSzTbl[0][++iTbs][numRb-1]/8 < effBo) + { + iTbs++; + } + rbAllocinfo->rbsReq = numRb; + rbAllocinfo->tbInfo[0].bytesReq = rgTbSzTbl[0][iTbs][numRb-1]/8; + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + if(rbAllocinfo->dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + rbAllocinfo->tbInfo[0].bytesReq = + rgSCHCmnCalcDwPtsTbSz(cell, effBo, &numRb, &iTbs, 1, cfi); + } +#endif + /* DwPTS Scheduling Changes End */ + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, rbAllocinfo->tbInfo[0].imcs); + } + else + { + RETVALUE(RFAILED); + } + } + + /* Update the subframe Allocated BW field */ + rbAllocinfo->dlSf->bwAssigned = rbAllocinfo->dlSf->bwAssigned + \ + rbAllocinfo->rbsReq; + rbAllocinfo->rnti = raCb->tmpCrnti; + rbAllocinfo->tbInfo[0].tbCb = &raCb->dlHqE->msg4Proc->tbInfo[0]; + rbAllocinfo->tbInfo[0].schdlngForTb = TRUE; + rbAllocinfo->tbInfo[0].noLyr = 1; + + RETVALUE(ROK); +} + +#ifdef LTE_TDD +/** + * @brief This function implements scheduling for RA Response. + * + * @details + * + * Function: rgSCHCmnDlRaRsp + * Purpose: Downlink scheduling for RA responses. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRaRsp +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlRaRsp(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLteTimingInfo frm; + CmLteTimingInfo schFrm; + RgSchDlSf *subFrm; + U16 rarnti; + U8 i; + U8 noRaRnti=0; + U8 raIdx; + RgSchTddRachRspLst *rachRsp; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 sfnIdx; + U8 subfrmIdx; + U16 rntiIdx=0; + TRC2(rgSCHCmnDlRaRsp); + + frm = cell->crntTime; + RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA); + + /* Compute the subframe for which allocation is being made */ + /* essentially, we need pointer to the dl frame for this subframe */ + subFrm = rgSCHUtlSubFrmGet(cell, frm); + + /* Get the RACH Response scheduling related information + * for the subframe with RA index */ + raIdx = rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][frm.subframe]-1; + + rachRsp = &cell->rachRspLst[raIdx]; + + for(sfnIdx = 0; sfnIdx < rachRsp->numRadiofrms; sfnIdx++) + { + /* For all scheduled RACH Responses in SFNs */ + schFrm = frm; + RG_SCH_CMN_DECR_FRAME(schFrm.sfn, rachRsp->rachRsp[sfnIdx].sfnOffset); + /* For all scheduled RACH Responses in subframes */ + for(subfrmIdx = 0; + subfrmIdx < rachRsp->rachRsp[sfnIdx].numSubfrms; subfrmIdx++) + { + schFrm.subframe = rachRsp->rachRsp[sfnIdx].subframe[subfrmIdx]; + /* compute the last RA RNTI used in the previous subframe */ + raIdx = (((schFrm.sfn % cell->raInfo.maxRaSize) * \ + RGSCH_NUM_SUB_FRAMES * RGSCH_MAX_RA_RNTI_PER_SUBFRM) \ + + schFrm.subframe); + + /* For all RA RNTIs within a subframe */ + + for(i=0; (i < RGSCH_MAX_RA_RNTI_PER_SUBFRM) && \ + (noRaRnti < RGSCH_MAX_TDD_RA_RSP_ALLOC); i++) + { + rarnti = (schFrm.subframe + RGSCH_NUM_SUB_FRAMES*i + 1); + rntiIdx = (raIdx + RGSCH_NUM_SUB_FRAMES*i); + + if (cell->raInfo.raReqLst[rntiIdx].first != NULLP) + { + /* compute the next RA RNTI */ + if (rgSCHCmnRaRspAlloc(cell, subFrm, rntiIdx, + rarnti, noRaRnti, allocInfo) != ROK) + { + /* The resources are exhausted */ + break; + } + noRaRnti++; + } + } + noRaRnti=0; + } + } + + RETVOID; +} +#else +/** + * @brief This function implements scheduling for RA Response. + * + * @details + * + * Function: rgSCHCmnDlRaRsp + * Purpose: Downlink scheduling for RA responses. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRaRsp //FDD +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlRaRsp(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLteTimingInfo frm; + CmLteTimingInfo winStartFrm; + RgSchDlSf *subFrm; + U8 winStartIdx; + U8 winGap; + U8 rarnti; + U8 raIdx; + RgSchCmnCell *sched; + U8 i,noRaRnti=0; + TRC2(rgSCHCmnDlRaRsp); + + frm = cell->crntTime; + RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA); + + /* Compute the subframe for which allocation is being made */ + /* essentially, we need pointer to the dl frame for this subframe */ + subFrm = rgSCHUtlSubFrmGet(cell, frm); + sched = RG_SCH_CMN_GET_CELL(cell); + + /* ccpu00132523 - Window Start calculated by considering RAR window size, + * RAR Wait period, Subframes occuppied for respective preamble format*/ + winGap = (sched->dl.numRaSubFrms-1) + (cell->rachCfg.raWinSize-1) + +RGSCH_RARSP_WAIT_PERIOD; + + /* Window starting occassion is retrieved using the gap and tried to + * fit to the size of raReqLst array*/ + RGSCHDECRFRMCRNTTIME(frm, winStartFrm, winGap); + + //5G_TODO TIMING update. Need to check + winStartIdx = (winStartFrm.sfn & 1) * RGSCH_MAX_RA_RNTI+ winStartFrm.subframe; + + for(i = 0; ((i < cell->rachCfg.raWinSize) && (noRaRnti < RG_SCH_CMN_MAX_CMN_PDCCH)); i++) + { + raIdx = (winStartIdx + i) % RGSCH_RAREQ_ARRAY_SIZE; + + if (cell->raInfo.raReqLst[raIdx].first != NULLP) + { + allocInfo->raRspAlloc[noRaRnti].biEstmt = \ + (!i * RGSCH_ONE_BIHDR_SIZE); + rarnti = raIdx % RGSCH_MAX_RA_RNTI+ 1; + if (rgSCHCmnRaRspAlloc(cell, subFrm, raIdx, + rarnti, noRaRnti, allocInfo) != ROK) + { + /* The resources are exhausted */ + break; + } + /* ccpu00132523- If all the RAP ids are not scheduled then need not + * proceed for next RA RNTIs*/ + if(allocInfo->raRspAlloc[noRaRnti].numRapids < cell->raInfo.raReqLst[raIdx].count) + { + break; + } + noRaRnti++; /* Max of RG_SCH_CMN_MAX_CMN_PDCCH RARNTIs + for response allocation */ + } + } + RETVOID; +} +#endif + + +/** + * @brief This function allocates the resources for an RARNTI. + * + * @details + * + * Function: rgSCHCmnRaRspAlloc + * Purpose: Allocate resources to a RARNTI. + * 0. Allocate PDCCH for sending the response. + * 1. Locate the number of RA requests pending for the RARNTI. + * 2. Compute the size of data to be built. + * 3. Using common channel CQI, compute the number of RBs. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell, + * @param[in] RgSchDlSf *subFrm, + * @param[in] U16 rarnti, + * @param[in] U8 noRaRnti + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnRaRspAlloc +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +U16 raIndex, +U16 rarnti, +U8 noRaRnti, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE S16 rgSCHCmnRaRspAlloc(cell,subFrm,raIndex,rarnti,noRaRnti,allocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +U16 raIndex; +U16 rarnti; +U8 noRaRnti; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + U16 noBytes; + U32 rb = 0; + U32 tbs; + /*ccpu00116700,ccpu00116708- Corrected the wrong type for mcs*/ + U8 mcs; + CmLListCp *reqLst; + /* RACH handling related changes */ + Bool isAlloc = FALSE; + static U8 schdNumRapid = 0; + U8 remNumRapid = 0; + U8 nPrb = 0; + S32 allwdTbSz = 0; +#ifdef LTE_TDD + U16 lostRe; + U8 cfi = cellDl->currCfi; +#endif + + TRC2(rgSCHCmnRaRspAlloc); +#ifndef RGR_V1 + UNUSED(cellUl); +#endif + + /* ccpu00132523: Resetting the schdRap Id count in every scheduling subframe*/ + if(noRaRnti == 0) + { + schdNumRapid = 0; + } + + + if (subFrm->bw == subFrm->bwAssigned) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "bw == bwAssigned RARNTI:%d",rarnti); + RETVALUE(RFAILED); + } + + reqLst = &cell->raInfo.raReqLst[raIndex]; + if (reqLst->count == 0) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "reqLst Count=0 RARNTI:%d",rarnti); + RETVALUE(RFAILED); + } + remNumRapid = reqLst->count; + +#ifdef RGR_V1 + /* Limit number of rach rsps to maxMsg3PerUlsf */ + if ( schdNumRapid+remNumRapid > cellUl->maxMsg3PerUlSf ) + { + remNumRapid = cellUl->maxMsg3PerUlSf-schdNumRapid; + } +#endif + + while (remNumRapid) + { + /* Try allocating for as many RAPIDs as possible */ + /* BI sub-header size to the tbSize requirement */ + noBytes = RGSCH_GET_RAR_BYTES(remNumRapid) +\ + allocInfo->raRspAlloc[noRaRnti].biEstmt; + if ((allwdTbSz = rgSCHUtlGetAllwdCchTbSz(noBytes*8, &nPrb, &mcs)) == -1) + { + remNumRapid--; + continue; + } + + /* rgSCHCmnClcRbAllocForFxdTb(cell, allwdTbSz/8, cellDl->ccchCqi, &rb);*/ + if(cellDl->bitsPerRb==0) + { + while ((rgTbSzTbl[0][0][rb]) <(U32) allwdTbSz) + { + rb++; + } + rb = rb+1; + } + else + { + rb = RGSCH_CEIL(allwdTbSz, cellDl->bitsPerRb); + } + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + if (subFrm->sfType == RG_SCH_SPL_SF_DATA) + { + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, cfi); + + /* Calculate the less RE's because of DwPTS */ + lostRe = rb * (cellDl->noResPerRb[cfi] - + cellDl->numReDwPts[cfi]); + + /* Increase number of RBs in Spl SF to compensate for lost REs */ + rb += RGSCH_CEIL(lostRe, cellDl->numReDwPts[cfi]); + } +#endif + /* DwPTS Scheduling Changes End */ + + /*ccpu00115595- end*/ + if (rb > subFrm->bw - subFrm->bwAssigned) + { + remNumRapid--; + continue; + } + /* Allocation succeeded for 'remNumRapid' */ + isAlloc = TRUE; + tbs = allwdTbSz/8; + printf("\n!!!RAR alloc noBytes:%u,allwdTbSz:%u,tbs:%u,rb:%u\n", + noBytes,allwdTbSz,tbs,rb); + break; + } + if (!isAlloc) + { + RLOG_ARG0(L_INFO,DBG_CELLID,cell->cellId,"BW alloc Failed"); + RETVALUE(RFAILED); + } + + subFrm->bwAssigned = subFrm->bwAssigned + rb; + + /* Fill AllocInfo structure */ + allocInfo->raRspAlloc[noRaRnti].rnti = rarnti; + allocInfo->raRspAlloc[noRaRnti].tbInfo[0].bytesReq = tbs; + allocInfo->raRspAlloc[noRaRnti].rbsReq = rb; + allocInfo->raRspAlloc[noRaRnti].dlSf = subFrm; + allocInfo->raRspAlloc[noRaRnti].tbInfo[0].imcs = mcs; + allocInfo->raRspAlloc[noRaRnti].raIndex = raIndex; + /* RACH changes for multiple RAPID handling */ + allocInfo->raRspAlloc[noRaRnti].numRapids = remNumRapid; + allocInfo->raRspAlloc[noRaRnti].nPrb = nPrb; + allocInfo->raRspAlloc[noRaRnti].tbInfo[0].noLyr = 1; + allocInfo->raRspAlloc[noRaRnti].vrbgReq = RGSCH_CEIL(nPrb,MAX_5GTF_VRBG_SIZE); + schdNumRapid += remNumRapid; + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlAllocFillRbInfo + * + * Desc : Fills the start RB and the number of RBs for + * uplink allocation. + * + * Ret : void + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAllocFillRbInfo +( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUlAlloc *alloc +) +#else +PUBLIC Void rgSCHCmnUlAllocFillRbInfo(cell, sf, alloc) +RgSchCellCb *cell; +RgSchUlSf *sf; +RgSchUlAlloc *alloc; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 cfi = cellDl->currCfi; + + + TRC2(rgSCHCmnUlAllocFillRbInfo); + alloc->grnt.rbStart = (alloc->sbStart * cellUl->sbSize) + + cell->dynCfiCb.bwInfo[cfi].startRb; + + /* Num RBs = numSbAllocated * sbSize - less RBs in the last SB */ + alloc->grnt.numRb = (alloc->numSb * cellUl->sbSize); + + RETVOID; +} + +/** + * @brief Grant request for Msg3. + * + * @details + * + * Function : rgSCHCmnMsg3GrntReq + * + * This is invoked by downlink scheduler to request allocation + * for msg3. + * Steps: + * - Attempt to allocate msg3 in the current msg3 subframe + * Allocation attempt based on whether preamble is from group A + * and the value of MESSAGE_SIZE_GROUP_A + * - Link allocation with passed RNTI and msg3 HARQ process + * - Set the HARQ process ID (*hqProcIdRef) + * + * @param[in] RgSchCellCb *cell + * @param[in] CmLteRnti rnti + * @param[in] Bool preamGrpA + * @param[in] RgSchUlHqProcCb *hqProc + * @param[out] RgSchUlAlloc **ulAllocRef + * @param[out] U8 *hqProcIdRef + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnMsg3GrntReq +( +RgSchCellCb *cell, +CmLteRnti rnti, +Bool preamGrpA, +RgSchUlHqProcCb *hqProc, +RgSchUlAlloc **ulAllocRef, +U8 *hqProcIdRef +) +#else +PRIVATE Void rgSCHCmnMsg3GrntReq(cell, rnti, preamGrpA, hqProc, + ulAllocRef, hqProcIdRef) +RgSchCellCb *cell; +CmLteRnti rnti; +Bool preamGrpA; +RgSchUlHqProcCb *hqProc; +RgSchUlAlloc **ulAllocRef; +U8 *hqProcIdRef; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->msg3SchdIdx]; + RgSchUlHole *hole; + RgSchUlAlloc *alloc; + U8 iMcs; + U8 numSb; + + TRC2(rgSCHCmnMsg3GrntReq); + + *ulAllocRef = NULLP; + + /* Fix: ccpu00120610 Use remAllocs from subframe during msg3 allocation */ + if (*sf->allocCountRef >= cellUl->maxAllocPerUlSf) + { + RETVOID; + } + if (preamGrpA == FALSE) + { + numSb = cellUl->ra.prmblBNumSb; + iMcs = cellUl->ra.prmblBIMcs; + } + else + { + numSb = cellUl->ra.prmblANumSb; + iMcs = cellUl->ra.prmblAIMcs; + } + + if ((hole = rgSCHUtlUlHoleFirst(sf)) != NULLP) + { + if(*sf->allocCountRef == 0) + { + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + /* Reinitialize the hole */ + if (sf->holeDb->count == 1 && (hole->start == 0)) /* Sanity check of holeDb */ + { + hole->num = cell->dynCfiCb.bwInfo[cellDl->currCfi].numSb; + /* Re-Initialize available subbands because of CFI change*/ + hole->num = cell->dynCfiCb.bwInfo[cellDl->currCfi].numSb; + } + else + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Error! holeDb sanity check failed RNTI:%d",rnti); + } + } + if (numSb <= hole->num) + { + U8 iTbs; + alloc = rgSCHUtlUlAllocGetHole(sf, numSb, hole); + rgSCHCmnUlAllocFillRbInfo(cell, sf, alloc); + alloc->grnt.iMcs = iMcs; + alloc->grnt.iMcsCrnt = iMcs; + iTbs = rgSCHCmnUlGetITbsFrmIMcs(iMcs); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgTbSzTbl[0], iTbs); + /* To include the length and ModOrder in DataRecp Req.*/ + alloc->grnt.datSz = rgTbSzTbl[0][iTbs][alloc->grnt.numRb-1] / 8; + RG_SCH_UL_MCS_TO_MODODR(iMcs, alloc->grnt.modOdr); + /* RACHO : setting nDmrs to 0 and UlDelaybit to 0*/ + alloc->grnt.nDmrs = 0; + alloc->grnt.hop = 0; + alloc->grnt.delayBit = 0; + alloc->grnt.isRtx = FALSE; + *ulAllocRef = alloc; + *hqProcIdRef = (cellUl->msg3SchdHqProcIdx); + hqProc->procId = *hqProcIdRef; + hqProc->ulSfIdx = (cellUl->msg3SchdIdx); + alloc->rnti = rnti; + alloc->ue = NULLP; + alloc->pdcch = FALSE; + alloc->forMsg3 = TRUE; + alloc->hqProc = hqProc; + rgSCHUhmNewTx(hqProc, (U8)(cell->rachCfg.maxMsg3Tx - 1), alloc); + //RLOG_ARG4(L_DEBUG,DBG_CELLID,cell->cellId, + printf( + "\nRNTI:%d MSG3 ALLOC proc(%p)procId(%d)schdIdx(%d)\n", + alloc->rnti, + ((PTR)alloc->hqProc), + alloc->hqProc->procId, + alloc->hqProc->ulSfIdx); + RLOG_ARG2(L_DEBUG,DBG_CELLID,cell->cellId, + "alloc(%p)maxMsg3Tx(%d)", + ((PTR)alloc), + cell->rachCfg.maxMsg3Tx); + } + } + + RETVOID; +} + + +/** + * @brief This function determines the allocation limits and + * parameters that aid in DL scheduling. + * + * @details + * + * Function: rgSCHCmnDlSetUeAllocLmt + * Purpose: This function determines the Maximum RBs + * a UE is eligible to get based on softbuffer + * limitation and cell->>>maxDlBwPerUe. The Codeword + * specific parameters like iTbs, eff and noLyrs + * are also set in this function. This function + * is called while UE configuration and UeDlCqiInd. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cellCb + * @param[in] RgSchCmnDlUe *ueDl + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlSetUeAllocLmt +( +RgSchCellCb *cell, +RgSchCmnDlUe *ueDl, +Bool isEmtcUe +) +#else +PRIVATE Void rgSCHCmnDlSetUeAllocLmt(cell, ueDl, isEmtcUe) +RgSchCellCb *cell; +RgSchCmnDlUe *ueDl; +Bool isEmtcUe; +#endif +{ + U8 modOrder; + U32 maxRb; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 cfi = cellSch->dl.currCfi; + + TRC2(rgSCHCmnDlSetUeAllocLmt); + +#ifdef EMTC_ENABLE + if(TRUE == isEmtcUe) + { + /* ITbs for CW0 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].iTbs[0] = (*(RgSchEmtcCmnCqiToTbs *)(cellSch->dl.emtcCqiToTbsTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].cqi]; + /* ITbs for CW0 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].iTbs[1] = (*(RgSchEmtcCmnCqiToTbs *)(cellSch->dl.emtcCqiToTbsTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].cqi]; + /* Eff for CW0 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].eff[0] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].iTbs[0]]; + /* Eff for CW0 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].eff[1] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].iTbs[1]]; + + /* ITbs for CW1 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].iTbs[0] = (*(RgSchEmtcCmnCqiToTbs *)(cellSch->dl.emtcCqiToTbsTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].cqi]; + /* ITbs for CW1 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].iTbs[1] = (*(RgSchEmtcCmnCqiToTbs *)(cellSch->dl.emtcCqiToTbsTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].cqi]; + /* Eff for CW1 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].eff[0] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].iTbs[0]]; + /* Eff for CW1 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].eff[1] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].iTbs[1]]; + } + else +#endif + { + /* ITbs for CW0 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].iTbs[0] = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].cqi]; + /* ITbs for CW0 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].iTbs[1] = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].cqi]; + /* Eff for CW0 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].eff[0] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].iTbs[0]]; + /* Eff for CW0 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[0].eff[1] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[0].iTbs[1]]; + + /* ITbs for CW1 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].iTbs[0] = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].cqi]; + /* ITbs for CW1 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].iTbs[1] = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].cqi]; + /* Eff for CW1 for 1 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].eff[0] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].iTbs[0]]; + /* Eff for CW1 for 2 Layer Tx */ + ueDl->mimoInfo.cwInfo[1].eff[1] = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\ + [ueDl->mimoInfo.cwInfo[1].iTbs[1]]; + } + +//#ifdef DL_LA + // ueDl->laCb.cqiBasediTbs = ueDl->mimoInfo.cwInfo[0].iTbs[0] * 100; +//#endif + /* Assigning noLyrs to each CW assuming optimal Spatial multiplexing + * capability */ + (ueDl->mimoInfo.ri/2 == 0)? (ueDl->mimoInfo.cwInfo[0].noLyr = 1) : \ + (ueDl->mimoInfo.cwInfo[0].noLyr = ueDl->mimoInfo.ri/2); + ueDl->mimoInfo.cwInfo[1].noLyr = ueDl->mimoInfo.ri - ueDl->mimoInfo.cwInfo[0].noLyr; + /* rg002.101:ccpu00102106: correcting DL harq softbuffer limitation logic. + * The maxTbSz is the maximum number of PHY bits a harq process can + * hold. Hence we limit our allocation per harq process based on this. + * Earlier implementation we misinterpreted the maxTbSz to be per UE + * per TTI, but in fact it is per Harq per TTI. */ + /* rg002.101:ccpu00102106: cannot exceed the harq Tb Size + * and harq Soft Bits limit.*/ + + /* Considering iTbs corresponding to 2 layer transmission for + * codeword0(approximation) and the maxLayers supported by + * this UE at this point of time. */ + RG_SCH_CMN_TBS_TO_MODODR(ueDl->mimoInfo.cwInfo[0].iTbs[1], modOrder); + + /* Bits/modOrder gives #REs, #REs/noResPerRb gives #RBs */ + /* rg001.301 -MOD- [ccpu00119213] : avoiding wraparound */ + maxRb = ((ueDl->maxSbSz)/(cellSch->dl.noResPerRb[cfi] * modOrder *\ + ueDl->mimoInfo.ri)); + if (cellSch->dl.isDlFreqSel) + { + /* Rounding off to left nearest multiple of RBG size */ + maxRb -= maxRb % cell->rbgSize; + } + ueDl->maxRb = RGSCH_MIN(maxRb, cellSch->dl.maxDlBwPerUe); + if (cellSch->dl.isDlFreqSel) + { + /* Rounding off to right nearest multiple of RBG size */ + if (ueDl->maxRb % cell->rbgSize) + { + ueDl->maxRb += (cell->rbgSize - + (ueDl->maxRb % cell->rbgSize)); + } + } + + /* Set the index of the cwInfo, which is better in terms of + * efficiency. If RI<2, only 1 CW, hence btrCwIdx shall be 0 */ + if (ueDl->mimoInfo.ri < 2) + { + ueDl->mimoInfo.btrCwIdx = 0; + } + else + { + if (ueDl->mimoInfo.cwInfo[0].eff[ueDl->mimoInfo.cwInfo[0].noLyr-1] <\ + ueDl->mimoInfo.cwInfo[1].eff[ueDl->mimoInfo.cwInfo[1].noLyr-1]) + { + ueDl->mimoInfo.btrCwIdx = 1; + } + else + { + ueDl->mimoInfo.btrCwIdx = 0; + } + } + + RETVOID; + } + +#ifdef DL_LA + +/** + * @brief This function updates TX Scheme. + * + * @details + * + * Function: rgSCHCheckAndSetTxScheme + * Purpose: This function determines the Maximum RBs + * a UE is eligible to get based on softbuffer + * limitation and cell->>>maxDlBwPerUe. The Codeword + * specific parameters like iTbs, eff and noLyrs + * are also set in this function. This function + * is called while UE configuration and UeDlCqiInd. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCheckAndSetTxScheme +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCheckAndSetTxScheme(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue ,cell); + U8 cfi = cellSch->dl.currCfi; + U8 maxiTbs; + U8 cqiBasediTbs; + U8 actualiTbs; + + TRC2(rgSCHCheckAndSetTxScheme); + + maxiTbs = (*(RgSchCmnCqiToTbs*)(cellSch->dl.cqiToTbsTbl[0][cfi]))\ + [RG_SCH_CMN_MAX_CQI - 1]; + cqiBasediTbs = (ueDl->laCb[0].cqiBasediTbs)/100; + actualiTbs = ueDl->mimoInfo.cwInfo[0].iTbs[0]; + + if((actualiTbs < RG_SCH_TXSCHEME_CHNG_ITBS_FACTOR) && (cqiBasediTbs > + actualiTbs) && ((cqiBasediTbs - actualiTbs) > RG_SCH_TXSCHEME_CHNG_THRSHD)) + { + RG_SCH_CMN_SET_FORCE_TD(ue,cell, RG_SCH_CMN_TD_TXSCHEME_CHNG); + } + + if(actualiTbs >= maxiTbs) + { + RG_SCH_CMN_UNSET_FORCE_TD(ue,cell, RG_SCH_CMN_TD_TXSCHEME_CHNG); + } + + RETVOID; +} + +/** + * @brief This function determines the allocation limits and + * parameters that aid in DL scheduling. + * + * @details + * + * Function: rgSCHCmnDlSetUeAllocLmtLa + * Purpose: This function determines the Maximum RBs + * a UE is eligible to get based on softbuffer + * limitation and cell->>>maxDlBwPerUe. The Codeword + * specific parameters like iTbs, eff and noLyrs + * are also set in this function. This function + * is called while UE configuration and UeDlCqiInd. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlSetUeAllocLmtLa +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnDlSetUeAllocLmtLa(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + U8 modOrder; + U32 maxRb; + U8 reportediTbs; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 cfi = cellSch->dl.currCfi; + U8 maxiTbs; + U8 cwIdx = 0; + + TRC2(rgSCHCmnDlSetUeAllocLmtLa); + + maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1]; + if(ueDl->cqiFlag == TRUE) + { + for(cwIdx=0; cwIdx < RG_SCH_CMN_MAX_CW_PER_UE; cwIdx++) + { + S32 iTbsNew; + + /* Calcluating the reported iTbs for code word 0 */ + reportediTbs = ue->ue5gtfCb.mcs; + + iTbsNew = (S32) reportediTbs; + + if(!ueDl->laCb[cwIdx].notFirstCqi) + { + /* This is the first CQI report from UE */ + ueDl->laCb[cwIdx].cqiBasediTbs = (iTbsNew * 100); + ueDl->laCb[cwIdx].notFirstCqi = TRUE; + } + else if ((RG_ITBS_DIFF(reportediTbs, ueDl->mimoInfo.cwInfo[cwIdx].iTbs[0])) > 5) + { + /* Ignore this iTBS report and mark that last iTBS report was */ + /* ignored so that subsequently we reset the LA algorithm */ + ueDl->laCb[cwIdx].lastiTbsIgnored = TRUE; + ueDl->laCb[cwIdx].numLastiTbsIgnored++; + if( ueDl->laCb[cwIdx].numLastiTbsIgnored > 10) + { + /* CQI reported by UE is not catching up. Reset the LA algorithm */ + ueDl->laCb[cwIdx].cqiBasediTbs = (iTbsNew * 100); + ueDl->laCb[cwIdx].deltaiTbs = 0; + ueDl->laCb[cwIdx].lastiTbsIgnored = FALSE; + ueDl->laCb[cwIdx].numLastiTbsIgnored = 0; + } + } + else + { + if (ueDl->laCb[cwIdx].lastiTbsIgnored != TRUE) + { + ueDl->laCb[cwIdx].cqiBasediTbs = ((20 * iTbsNew * 100) + + (80 * ueDl->laCb[cwIdx].cqiBasediTbs))/100; + } + else + { + /* Reset the LA as iTbs in use caught up with the value */ + /* reported by UE. */ + ueDl->laCb[cwIdx].cqiBasediTbs = ((20 * iTbsNew * 100) + + (80 * ueDl->mimoInfo.cwInfo[cwIdx].iTbs[0] * 100))/100; + ueDl->laCb[cwIdx].deltaiTbs = 0; + ueDl->laCb[cwIdx].lastiTbsIgnored = FALSE; + } + } + + iTbsNew = (ueDl->laCb[cwIdx].cqiBasediTbs + ueDl->laCb[cwIdx].deltaiTbs)/100; + + RG_SCH_CHK_ITBS_RANGE(iTbsNew, maxiTbs); + + ueDl->mimoInfo.cwInfo[cwIdx].iTbs[0] = RGSCH_MIN(iTbsNew, cell->thresholds.maxDlItbs); + //ueDl->mimoInfo.cwInfo[cwIdx].iTbs[1] = ueDl->mimoInfo.cwInfo[cwIdx].iTbs[0]; +#ifdef RG_5GTF + ue->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[cwIdx].iTbs[0]; + /* + printf("reportediTbs[%d] cqiBasediTbs[%d] deltaiTbs[%d] iTbsNew[%d] mcs[%d] cwIdx[%d]\n", + reportediTbs, ueDl->laCb[cwIdx].cqiBasediTbs, ueDl->laCb[cwIdx].deltaiTbs, + iTbsNew, ue->ue5gtfCb.mcs, cwIdx); + */ +#endif + + if((ue->mimoInfo.txMode != RGR_UE_TM_3) && (ue->mimoInfo.txMode != RGR_UE_TM_4)) + { + break; + } + } + ueDl->cqiFlag = FALSE; + } + + + RETVOID; +} +#endif +/*********************************************************** + * + * Func : rgSCHCmnDlUeResetTemp + * + * Desc : Reset whatever variables where temporarily used + * during UE scheduling. + * + * Ret : Void + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlHqPResetTemp +( +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnDlHqPResetTemp(hqP) +RgSchDlHqProcCb *hqP; +#endif +{ + + TRC2(rgSCHCmnDlHqPResetTemp); + + /* Fix: syed having a hqP added to Lists for RB assignment rather than + * a UE, as adding UE was limiting handling some scenarios */ + hqP->reqLnk.node = (PTR)NULLP; + hqP->schdLstLnk.node = (PTR)NULLP; + + RETVOID; +} /* rgSCHCmnDlHqPResetTemp */ + +/*********************************************************** + * + * Func : rgSCHCmnDlUeResetTemp + * + * Desc : Reset whatever variables where temporarily used + * during UE scheduling. + * + * Ret : Void + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlUeResetTemp +( +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnDlUeResetTemp(ue, hqP) +RgSchUeCb *ue; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *cmnUe = RG_SCH_CMN_GET_DL_UE(ue,hqP->hqE->cell); +#ifdef LTE_ADV + Void *tmpCb; +#endif + + TRC2(rgSCHCmnDlUeResetTemp); + + /* Fix : syed check for UE's existence was useless. + * Instead we need to check that reset is done only for the + * information of a scheduled harq proc, which is cmnUe->proc. + * Reset should not be done for non-scheduled hqP */ + if((cmnUe->proc == hqP) || (cmnUe->proc == NULLP)) + { + cmnUe->proc = NULLP; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, hqP->hqE->cell); +#ifdef LTE_ADV + tmpCb = allocInfo->laaCb; +#endif + cmMemset((U8 *)allocInfo, (U8)0, sizeof(RgSchDlRbAlloc)); + allocInfo->rnti = ue->ueId; +#ifdef LTE_ADV + allocInfo->laaCb = tmpCb; +#endif + /* Fix: syed moving this to a common function for both scheduled + * and non-scheduled UEs */ + cmnUe->outStndAlloc = 0; + } + rgSCHCmnDlHqPResetTemp(hqP); + + RETVOID; +} /* rgSCHCmnDlUeResetTemp */ + +/*********************************************************** + * + * Func : rgSCHCmnUlUeResetTemp + * + * Desc : Reset whatever variables where temporarily used + * during UE scheduling. + * + * Ret : Void + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlUeResetTemp +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlUeResetTemp(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnUlUe *cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue,cell); + + TRC2(rgSCHCmnUlUeResetTemp); + + cmMemset((U8 *)&cmnUlUe->alloc, (U8)0, sizeof(cmnUlUe->alloc)); + + RETVOID; +} /* rgSCHCmnUlUeResetTemp */ + + + +/** + * @brief This function fills the PDCCH information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillPdcch + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlRbAlloc + * during common channel scheduling(P, SI, RA - RNTI's). + * + * Invoked by: Downlink Scheduler + * + * @param[out] RgSchPdcch* pdcch + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnFillPdcch +( +RgSchCellCb *cell, +RgSchPdcch *pdcch, +RgSchDlRbAlloc *rbAllocInfo +) +#else +PUBLIC Void rgSCHCmnFillPdcch(cell, pdcch, rbAllocInfo) +RgSchCellCb *cell; +RgSchPdcch *pdcch; +RgSchDlRbAlloc *rbAllocInfo; +#endif +{ + + TRC2(rgSCHCmnFillPdcch); + + /* common channel pdcch filling, + * only 1A and Local is supported */ + pdcch->rnti = rbAllocInfo->rnti; + pdcch->dci.dciFormat = rbAllocInfo->dciFormat; + switch(rbAllocInfo->dciFormat) + { +#ifdef RG_5GTF /* ANOOP: ToDo: DCI format B1/B2 filling */ + case TFU_DCI_FORMAT_B1: + { + /* ToDo: Anoop */ + pdcch->dci.u.formatB1Info.formatType = 0; + pdcch->dci.u.formatB1Info.xPDSCHRange = rbAllocInfo->tbInfo[0].cmnGrnt.xPDSCHRange; + pdcch->dci.u.formatB1Info.RBAssign = rbAllocInfo->tbInfo[0].cmnGrnt.rbAssign; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.hqProcId = 0; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.ndi = 0; + //pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.ndi = rbAllocInfo->tbInfo[0].ndi; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.RV = rbAllocInfo->tbInfo[0].cmnGrnt.rv; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.bmiHqAckNack = 0; + pdcch->dci.u.formatB1Info.CSI_BSI_BRI_Req = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_TxTiming = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_SymbIdx = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_ProcInd = 0; + pdcch->dci.u.formatB1Info.xPUCCH_TxTiming = 0; + //TODO_SID: Need to update + pdcch->dci.u.formatB1Info.freqResIdx_xPUCCH = 0; + pdcch->dci.u.formatB1Info.beamSwitch = 0; + pdcch->dci.u.formatB1Info.SRS_Config = 0; + pdcch->dci.u.formatB1Info.SRS_Symbol = 0; + //TODO_SID: Need to check.Currently setting 0(1 layer, ports(8) w/o OCC). + pdcch->dci.u.formatB1Info.AntPorts_numLayers = 0; + pdcch->dci.u.formatB1Info.SCID = rbAllocInfo->tbInfo[0].cmnGrnt.SCID; + //TODO_SID: Hardcoding TPC command to 1 i.e. No change + pdcch->dci.u.formatB1Info.tpcCmd = 1; //tpc; + pdcch->dci.u.formatB1Info.DL_PCRS = 0; + + break; /* case TFU_DCI_FORMAT_B1: */ + } + + case TFU_DCI_FORMAT_B2: + { + //printf(" RG_5GTF:: Pdcch filling with DCI format B2\n"); + /* ToDo: Anoop */ + break; /* case TFU_DCI_FORMAT_B2: */ + } +#endif + case TFU_DCI_FORMAT_1A: + pdcch->dci.u.format1aInfo.isPdcchOrder = FALSE; + + /*Nprb indication at PHY for common Ch + *setting least significant bit of tpc field to 1 if + nPrb=3 and 0 otherwise. */ + if (rbAllocInfo->nPrb == 3) + { + pdcch->dci.u.format1aInfo.t.pdschInfo.tpcCmd = 1; + } + else + { + pdcch->dci.u.format1aInfo.t.pdschInfo.tpcCmd = 0; + } + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.nGap2.pres = NOTPRSNT; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.isLocal = TRUE; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.mcs = \ + rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.ndi = 0; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.rv = 0; + /* Add RIV CALC */ + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.alloc.type = + TFU_ALLOC_TYPE_RIV; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.alloc.u.riv = + rgSCHCmnCalcRiv (cell->bwCfg.dlTotalBw, + rbAllocInfo->allocInfo.raType2.rbStart, + rbAllocInfo->allocInfo.raType2.numRb); + +#ifdef LTE_TDD + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.pres = \ + FALSE; +#ifdef TFU_TDD + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.pres = TRUE; + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.val = 1; +#endif +#endif + break; /* case TFU_DCI_FORMAT_1A: */ + case TFU_DCI_FORMAT_1: + pdcch->dci.u.format1Info.tpcCmd = 0; + /* Avoiding this check,as we dont support Type1 RA */ +#ifdef RG_UNUSED + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { +#endif + pdcch->dci.u.format1Info.allocInfo.isAllocType0 = TRUE; + pdcch->dci.u.format1Info.allocInfo.resAllocMap[0] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 24) + & 0xff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[1] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 16) + & 0x00ff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[2] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 8) + & 0x0000ff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[3] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask & 0x000000ff)); +#ifdef RG_UNUSED + } +#endif + pdcch->dci.u.format1Info.allocInfo.harqProcId = 0; + pdcch->dci.u.format1Info.allocInfo.ndi = 0; + pdcch->dci.u.format1Info.allocInfo.mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format1Info.allocInfo.rv = 0; +#ifdef TFU_TDD + pdcch->dci.u.format1Info.dai = 1; +#endif + break; + default: + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Allocator's icorrect " + "dciForamt Fill RNTI:%d",rbAllocInfo->rnti); + break; + } + RETVOID; +} + +#ifdef LTE_TDD +/** + * @brief This function finds whether the subframe is special subframe or not. + * + * @details + * + * Function: rgSCHCmnIsSplSubfrm + * Purpose: This function finds the subframe index of the special subframe + * and finds whether the current DL index matches it or not. + * + * Invoked by: Scheduler + * + * @param[in] U8 splfrmCnt + * @param[in] U8 curSubfrmIdx + * @param[in] U8 periodicity + * @param[in] RgSchTddSubfrmInfo *subfrmInfo + * @return Bool + * + **/ +#ifdef ANSI +PRIVATE Bool rgSCHCmnIsSplSubfrm +( +U8 splfrmCnt, +U8 curSubfrmIdx, +U8 periodicity, +RgSchTddSubfrmInfo *subfrmInfo +) +#else +PRIVATE Bool rgSCHCmnIsSplSubfrm(splfrmCnt, curSubfrmIdx, periodicity, subfrmInfo) +U8 splfrmCnt; +U8 curSubfrmIdx; +U8 periodicity; +RgSchTddSubfrmInfo *subfrmInfo; +#endif +{ + U8 dlSfCnt = 0; + U8 splfrmIdx = 0; + + TRC2(rgSCHCmnIsSplSubfrm); + + if(splfrmCnt > 0) + { + if(periodicity == RG_SCH_CMN_5_MS_PRD) + { + if(splfrmCnt%2) + { + dlSfCnt = ((splfrmCnt-1)/2) *\ + (subfrmInfo->numFrmHf1 + subfrmInfo->numFrmHf2); + dlSfCnt = dlSfCnt + subfrmInfo->numFrmHf1; + } + else + { + dlSfCnt = (splfrmCnt/2) * \ + (subfrmInfo->numFrmHf1 + subfrmInfo->numFrmHf2); + } + } + else + { + dlSfCnt = splfrmCnt * subfrmInfo->numFrmHf1; + } + splfrmIdx = RG_SCH_CMN_SPL_SUBFRM_1 +\ + (periodicity*splfrmCnt - dlSfCnt); + } + else + { + splfrmIdx = RG_SCH_CMN_SPL_SUBFRM_1; + } + + if(splfrmIdx == curSubfrmIdx) + { + RETVALUE(TRUE); + } + + RETVALUE(FALSE); +} + +/** + * @brief This function updates DAI or UL index. + * + * @details + * + * Function: rgSCHCmnUpdHqAndDai + * Purpose: Updates the DAI based on UL-DL Configuration + * index and UE. It also updates the HARQ feedback + * time and 'm' index. + * + * Invoked by: TOM + * + * @param[in] RgDlHqProcCb *hqP + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchDlHqTbCb *tbCb + * @param[in] U8 tbAllocIdx + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdHqAndDai +( +RgSchDlHqProcCb *hqP, +RgSchDlSf *subFrm, +RgSchDlHqTbCb *tbCb, +U8 tbAllocIdx +) +#else +PRIVATE Void rgSCHCmnUpdHqAndDai(hqP, subFrm, tbCb,tbAllocIdx) +RgSchDlHqProcCb *hqP; +RgSchDlSf *subFrm; +RgSchDlHqTbCb *tbCb; +U8 tbAllocIdx; +#endif +{ + RgSchUeCb *ue = hqP->hqE->ue; + + TRC2(rgSCHCmnUpdHqAndDai); + + if(subFrm != NULLP) + { + /* set the time at which UE shall send the feedback + * for this process */ + tbCb->fdbkTime.sfn = (tbCb->timingInfo.sfn + \ + subFrm->dlFdbkInfo.sfnOffset) % RGSCH_MAX_SFN; + tbCb->fdbkTime.subframe = subFrm->dlFdbkInfo.subframe; + tbCb->m = subFrm->dlFdbkInfo.m; + } + else + { + /* set the time at which UE shall send the feedback + * for this process */ + tbCb->fdbkTime.sfn = (tbCb->timingInfo.sfn + \ + hqP->subFrm->dlFdbkInfo.sfnOffset) % RGSCH_MAX_SFN; + tbCb->fdbkTime.subframe = hqP->subFrm->dlFdbkInfo.subframe; + tbCb->m = hqP->subFrm->dlFdbkInfo.m; + } + + /* ccpu00132340-MOD- DAI need to be updated for first TB only*/ + if(ue && !tbAllocIdx) + { + Bool havePdcch = (tbCb->hqP->pdcch ? TRUE : FALSE); + U8 dlDai; + + dlDai = rgSCHCmnUpdDai(ue, &tbCb->fdbkTime, tbCb->m, havePdcch,tbCb->hqP, + &tbCb->dai); + if(havePdcch) + {/* Non SPS occasions */ + tbCb->hqP->pdcch->dlDai = dlDai; + /* hqP->ulDai is used for N1 resource filling + * when SPS occaions present in a bundle */ + tbCb->hqP->ulDai = tbCb->dai; + tbCb->hqP->dlDai = dlDai; + } + } + + /* Updatijng pucchFdbkIdx for both PUCCH or PUSCH + fdbk reception */ + tbCb->pucchFdbkIdx = tbCb->hqP->ulDai; + + RETVOID; +} + + +/** + * @brief This function updates DAI or UL index. + * + * @details + * + * Function: rgSCHCmnUpdDai + * Purpose: Updates the DAI in the ack-nack info, a valid + * ue should be passed + * + * Invoked by: TOM + * + * @param[in] RgDlHqProcCb *hqP + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchDlHqTbCb *tbCb + * @return U8 dlDai + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUpdDai +( +RgSchUeCb *ue, +CmLteTimingInfo *fdbkTime, +U8 m, +Bool havePdcch, +RgSchDlHqProcCb *hqP, +U8 *ulDai +) +#else +PUBLIC U8 rgSCHCmnUpdDai(ue, fdbkTime, m, havePdcch,tbCb,servCellId,hqP,ulDai) +RgSchUeCb *ue; +CmLteTimingInfo *fdbkTime; +U8 m; +Bool havePdcch; +RgSchDlHqProcCb *hqP; +U8 *ulDai; +#endif +{ + RgSchTddANInfo *anInfo; + U8 servCellIdx; + U8 ackNackFdbkArrSize; + + + TRC2(rgSCHCmnUpdDai); + + if(hqP != NULLP) + {/* Non SPS */ +#ifdef LTE_ADV + servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + ue); +#else + servCellIdx = RGSCH_PCELL_INDEX; +#endif + ackNackFdbkArrSize = hqP->hqE->cell->ackNackFdbkArrSize; + }else + {/* SPS on primary cell */ + servCellIdx = RGSCH_PCELL_INDEX; + ackNackFdbkArrSize = ue->cell->ackNackFdbkArrSize; + } + + + anInfo = rgSCHUtlGetUeANFdbkInfo(ue, fdbkTime,servCellIdx); + + /* If no ACK/NACK feedback already present, create a new one */ + if(NULLP == anInfo) + { + anInfo = &ue->cellInfo[servCellIdx]->anInfo[ue->cellInfo[servCellIdx]->nextFreeANIdx]; + anInfo->sfn = fdbkTime->sfn; + anInfo->subframe = fdbkTime->subframe; + anInfo->latestMIdx = m; + /* Fixing DAI value - ccpu00109162 */ + /* Handle TDD case as in MIMO definition of the function */ + anInfo->ulDai = 1; + if (havePdcch) + { + anInfo->dlDai = 1; + } + anInfo->isSpsOccasion = FALSE; + /* set the free Index to store Ack/Nack Information*/ + ue->cellInfo[servCellIdx]->nextFreeANIdx = (ue->cellInfo[servCellIdx]->nextFreeANIdx + 1) % + ackNackFdbkArrSize; + + } + else + { + anInfo->latestMIdx = m; + /* Fixing DAI value - ccpu00109162 */ + /* Handle TDD case as in MIMO definition of the function */ + anInfo->ulDai = anInfo->ulDai + 1; + if (havePdcch) + { + anInfo->dlDai = anInfo->dlDai + 1; + } + } +#ifdef LTE_ADV + /* ignoring the Scell check, + * for primary cell this field is unused*/ + if(hqP != NULLP) + {/* SPS*/ + anInfo->n1ResTpcIdx = hqP->tpc; + } + + if(ulDai) + {/* As this not required for release pdcch */ + *ulDai = anInfo->ulDai; + } +#endif + RETVALUE(anInfo->dlDai); + +} +#endif /* ifdef LTE_TDD */ + +PUBLIC U32 rgHqRvRetxCnt[4][2]; +PUBLIC U32 rgUlrate_grant; + +/** + * @brief This function fills the HqP TB with rbAllocInfo. + * + * @details + * + * Function: rgSCHCmnFillHqPTb + * Purpose: This function fills in the HqP TB with rbAllocInfo. + * + * Invoked by: rgSCHCmnFillHqPTb + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc *rbAllocInfo, + * @param[in] U8 tbAllocIdx + * @param[in] RgSchPdcch *pdcch + * @return Void + * + **/ +#ifdef LTEMAC_SPS +#ifdef ANSI +PUBLIC Void rgSCHCmnFillHqPTb +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +U8 tbAllocIdx, +RgSchPdcch *pdcch +) +#else +PUBLIC Void rgSCHCmnFillHqPTb(cell, rbAllocInfo, tbAllocIdx, pdcch) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +U8 tbAllocIdx; +RgSchPdcch *pdcch; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPTb +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +U8 tbAllocIdx, +RgSchPdcch *pdcch +) +#else +PRIVATE Void rgSCHCmnFillHqPTb(cell, rbAllocInfo, tbAllocIdx, pdcch) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +U8 tbAllocIdx; +RgSchPdcch *pdcch; +#endif +#endif /* LTEMAC_SPS */ +{ + RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchDlTbAllocInfo *tbAllocInfo = &rbAllocInfo->tbInfo[tbAllocIdx]; + RgSchDlHqTbCb *tbInfo = tbAllocInfo->tbCb; + RgSchDlHqProcCb *hqP = tbInfo->hqP; + + TRC2(rgSCHCmnFillHqPTb); + + /*ccpu00120365-ADD-if tb is disabled, set mcs=0,rv=1. + * Relevant for DCI format 2 & 2A as per 36.213-7.1.7.2 + */ + if ( tbAllocInfo->isDisabled) + { + + tbInfo->dlGrnt.iMcs = 0; + tbInfo->dlGrnt.rv = 1; + } + /* Fill for TB retransmission */ + else if (tbInfo->txCntr > 0) + { + + tbInfo->timingInfo = cmnCellDl->time; + /* Fix */ + if ((tbInfo->isAckNackDtx == TFU_HQFDB_DTX)) + { + tbInfo->dlGrnt.iMcs = tbAllocInfo->imcs; + rgHqRvRetxCnt[tbInfo->dlGrnt.rv][tbInfo->tbIdx]++; + } + else + { + tbInfo->dlGrnt.rv = rgSchCmnDlRvTbl[++(tbInfo->ccchSchdInfo.rvIdx) & 0x03]; + } + + /* fill the scheduler information of hqProc */ + tbInfo->ccchSchdInfo.totBytes = tbAllocInfo->bytesAlloc; + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,hqP->tbInfo,tbInfo->tbIdx ); + rgSCHDhmHqTbRetx(hqP->hqE, tbInfo->timingInfo, hqP, tbInfo->tbIdx); + } + /* Fill for TB transmission */ + else + { + /* Fill the HqProc */ + tbInfo->dlGrnt.iMcs = tbAllocInfo->imcs; + tbInfo->tbSz = tbAllocInfo->bytesAlloc; + tbInfo->timingInfo = cmnCellDl->time; + + tbInfo->dlGrnt.rv = rgSchCmnDlRvTbl[0]; + /* fill the scheduler information of hqProc */ + tbInfo->ccchSchdInfo.rvIdx = 0; + tbInfo->ccchSchdInfo.totBytes = tbAllocInfo->bytesAlloc; + /* DwPts Scheduling Changes Start */ + /* DwPts Scheduling Changes End */ + cell->measurements.dlBytesCnt += tbAllocInfo->bytesAlloc; + } + + /*ccpu00120365:-ADD-only add to subFrm list if tb is not disabled */ + if ( tbAllocInfo->isDisabled == FALSE ) + { + /* Set the number of transmitting SM layers for this TB */ + tbInfo->numLyrs = tbAllocInfo->noLyr; + /* Set the TB state as WAITING to indicate TB has been + * considered for transmission */ + tbInfo->state = HQ_TB_WAITING; + hqP->subFrm = rbAllocInfo->dlSf; + tbInfo->hqP->pdcch = pdcch; + //tbInfo->dlGrnt.numRb = rbAllocInfo->rbsAlloc; + rgSCHUtlDlHqPTbAddToTx(hqP->subFrm, hqP, tbInfo->tbIdx); + } + RETVOID; +} + +/** + * @brief This function fills the PDCCH DCI format 2 information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt2 + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmtB1B2 +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmtB1B2(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ + + TRC2(rgSCHCmnFillHqPPdcchDciFrmtB1B2) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + //Currently hardcoding values here. + //printf("Filling 5GTF UL DCI for rnti %d \n",alloc->rnti); + switch(rbAllocInfo->dciFormat) + { + case TFU_DCI_FORMAT_B1: + { + pdcch->dci.u.formatB1Info.formatType = 0; + pdcch->dci.u.formatB1Info.xPDSCHRange = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.xPDSCHRange; + pdcch->dci.u.formatB1Info.RBAssign = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rbAssign; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.hqProcId = hqP->procId; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.ndi = rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.RV = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + pdcch->dci.u.formatB1Info.u.rbAssignB1Val324.bmiHqAckNack = 0; + pdcch->dci.u.formatB1Info.CSI_BSI_BRI_Req = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_TxTiming = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_SymbIdx = 0; + pdcch->dci.u.formatB1Info.CSIRS_BRRS_ProcInd = 0; + pdcch->dci.u.formatB1Info.xPUCCH_TxTiming = 0; + //TODO_SID: Need to update + pdcch->dci.u.formatB1Info.freqResIdx_xPUCCH = 0; + pdcch->dci.u.formatB1Info.beamSwitch = 0; + pdcch->dci.u.formatB1Info.SRS_Config = 0; + pdcch->dci.u.formatB1Info.SRS_Symbol = 0; + //TODO_SID: Need to check.Currently setting 0(1 layer, ports(8) w/o OCC). + pdcch->dci.u.formatB1Info.AntPorts_numLayers = 0; + pdcch->dci.u.formatB1Info.SCID = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.SCID; + //TODO_SID: Hardcoding TPC command to 1 i.e. No change + pdcch->dci.u.formatB1Info.tpcCmd = 1; //tpc; + pdcch->dci.u.formatB1Info.DL_PCRS = 0; + break; + } + case TFU_DCI_FORMAT_B2: + { + pdcch->dci.u.formatB2Info.formatType = 1; + pdcch->dci.u.formatB2Info.xPDSCHRange = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.xPDSCHRange; + pdcch->dci.u.formatB2Info.RBAssign = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rbAssign; + pdcch->dci.u.formatB2Info.u.rbAssignB1Val324.hqProcId = hqP->procId; + pdcch->dci.u.formatB2Info.u.rbAssignB1Val324.mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.formatB2Info.u.rbAssignB1Val324.ndi = rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.formatB2Info.u.rbAssignB1Val324.RV = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + pdcch->dci.u.formatB2Info.u.rbAssignB1Val324.bmiHqAckNack = 0; + pdcch->dci.u.formatB2Info.CSI_BSI_BRI_Req = 0; + pdcch->dci.u.formatB2Info.CSIRS_BRRS_TxTiming = 0; + pdcch->dci.u.formatB2Info.CSIRS_BRRS_SymbIdx = 0; + pdcch->dci.u.formatB2Info.CSIRS_BRRS_ProcInd = 0; + pdcch->dci.u.formatB2Info.xPUCCH_TxTiming = 0; + //TODO_SID: Need to update + pdcch->dci.u.formatB2Info.freqResIdx_xPUCCH = 0; + pdcch->dci.u.formatB2Info.beamSwitch = 0; + pdcch->dci.u.formatB2Info.SRS_Config = 0; + pdcch->dci.u.formatB2Info.SRS_Symbol = 0; + //TODO_SID: Need to check.Currently setting 4(2 layer, ports(8,9) w/o OCC). + pdcch->dci.u.formatB2Info.AntPorts_numLayers = 4; + pdcch->dci.u.formatB2Info.SCID = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.SCID; + //TODO_SID: Hardcoding TPC command to 1 i.e. No change + pdcch->dci.u.formatB2Info.tpcCmd = 1; //tpc; + pdcch->dci.u.formatB2Info.DL_PCRS = 0; + break; + } + default: + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId," 5GTF_ERROR Allocator's icorrect " + "dciForamt Fill RNTI:%d",rbAllocInfo->rnti); + break; + } + + RETVOID; +} + +extern U32 totPcellSCell; +extern U32 addedForScell; +extern U32 addedForScell1; +extern U32 addedForScell2; +/** + * @brief This function fills the PDCCH information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcch + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnFillHqPPdcch +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnFillHqPPdcch(cell, rbAllocInfo, hqP) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnDlCell *cmnCell = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchPdcch *pdcch = rbAllocInfo->pdcch; + U8 tpc = 1; + + TRC2(rgSCHCmnFillHqPPdcch); + + if (hqP->hqE->ue) + { +#ifdef LTE_ADV + if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue, cell)) + { + tpc = hqP->tpc; + } + else +#endif + { + tpc = rgSCHPwrPucchTpcForUe(cell, hqP->hqE->ue); + } + /* Fix: syed moving this to a common function for both scheduled + * and non-scheduled UEs */ + + pdcch->ue = hqP->hqE->ue; + if (hqP->hqE->ue->csgMmbrSta == FALSE) + { + cmnCell->ncsgPrbCnt += rbAllocInfo->rbsAlloc; + } + cmnCell->totPrbCnt += rbAllocInfo->rbsAlloc; +#ifdef TENB_STATS + { + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlPrbUsg += + rbAllocInfo->rbsAlloc; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlSumCw0iTbs += + rbAllocInfo->tbInfo[0].iTbs; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlNumCw0iTbs ++; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlTpt += + (rbAllocInfo->tbInfo[0].bytesAlloc << 3); + +#ifdef LTE_ADV + totPcellSCell += (rbAllocInfo->tbInfo[0].bytesAlloc << 3); + if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue, cell)) + { + addedForScell += (rbAllocInfo->tbInfo[0].bytesAlloc << 3); + addedForScell1 += (rbAllocInfo->tbInfo[0].bytesAlloc << 3); +/* + printf (" Hqp %d cell %d addedForScell %lu addedForScell1 %lu sfn:sf %d:%d \n", + hqP->procId, + hqP->hqE->cell->cellId, + addedForScell, + addedForScell1, + cell->crntTime.sfn, + cell->crntTime.subframe); + */ + } +#endif + hqP->hqE->cell->tenbStats->sch.dlPrbUsage[0] += + rbAllocInfo->rbsAlloc; + hqP->hqE->cell->tenbStats->sch.dlSumCw0iTbs += + rbAllocInfo->tbInfo[0].iTbs; + hqP->hqE->cell->tenbStats->sch.dlNumCw0iTbs ++; + hqP->hqE->cell->tenbStats->sch.dlTtlTpt += + (rbAllocInfo->tbInfo[0].bytesAlloc << 3); + if (rbAllocInfo->tbInfo[1].schdlngForTb) + { + hqP->hqE->cell->tenbStats->sch.dlSumCw1iTbs += + rbAllocInfo->tbInfo[1].iTbs; + hqP->hqE->cell->tenbStats->sch.dlNumCw1iTbs ++; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlSumCw1iTbs += + rbAllocInfo->tbInfo[1].iTbs; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlNumCw1iTbs ++; + hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlTpt += + (rbAllocInfo->tbInfo[1].bytesAlloc << 3); + + +#ifdef LTE_ADV + if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue, cell)) + { + addedForScell += (rbAllocInfo->tbInfo[1].bytesAlloc << 3); + addedForScell2 += (rbAllocInfo->tbInfo[1].bytesAlloc << 3); +/* + printf (" Hqp %d cell %d addedForScell %lu addedForScell2 %lu \n", + hqP->procId, + hqP->hqE->cell->cellId, + addedForScell, + addedForScell2); + */ + } + totPcellSCell += (rbAllocInfo->tbInfo[1].bytesAlloc << 3); +#endif + + + hqP->hqE->cell->tenbStats->sch.dlTtlTpt += + (rbAllocInfo->tbInfo[1].bytesAlloc << 3); + } + /* + printf ("add DL TPT is %lu sfn:sf %d:%d \n", hqP->hqE->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(hqP->hqE->cell)].dlTpt , + cell->crntTime.sfn, + cell->crntTime.subframe); + */ + } +#endif + } + + pdcch->rnti = rbAllocInfo->rnti; + pdcch->dci.dciFormat = rbAllocInfo->dciFormat; + /* Update subframe and pdcch info in HqTb control block */ + switch(rbAllocInfo->dciFormat) + { +#ifdef RG_5GTF + case TFU_DCI_FORMAT_B1: + case TFU_DCI_FORMAT_B2: + { + // printf(" RG_5GTF:: Pdcch filling with DCI format B1/B2\n"); + rgSCHCmnFillHqPPdcchDciFrmtB1B2(cell, rbAllocInfo, hqP, \ + pdcch, tpc); + break; + } +#endif + default: + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Allocator's incorrect dciForamt Fill for RNTI:%d",rbAllocInfo->rnti); + break; + } + RETVOID; +} + +/** + * @brief This function fills the PDCCH DCI format 1 information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt1 + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1 +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ + +#ifdef LTE_TDD + RgSchTddANInfo *anInfo; +#endif + +#ifdef LTEMAC_SPS +/* For activation or reactivation, + * Harq ProcId should be 0 */ + RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP); +#endif + + TRC2(rgSCHCmnFillHqPPdcchDciFrmt1) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + pdcch->dci.u.format1Info.tpcCmd = tpc; + /* Avoiding this check,as we dont support Type1 RA */ +#ifdef RG_UNUSED + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { +#endif + pdcch->dci.u.format1Info.allocInfo.isAllocType0 = TRUE; + pdcch->dci.u.format1Info.allocInfo.resAllocMap[0] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 24) + & 0xff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[1] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 16) + & 0x00ff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[2] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 8) + & 0x0000ff); + pdcch->dci.u.format1Info.allocInfo.resAllocMap[3] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask & 0x000000ff)); +#ifdef RG_UNUSED + } +#endif +#ifdef LTEMAC_SPS + if ((!(hqP->tbInfo[0].txCntr)) && + (cmnHqDl != (RgSchCmnDlHqProc*)NULLP && + ((cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_ACTV) || + (cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_REACTV))) + ) + { + pdcch->dci.u.format1Info.allocInfo.harqProcId = 0; + } + else + { + pdcch->dci.u.format1Info.allocInfo.harqProcId = hqP->procId; + } +#else + pdcch->dci.u.format1Info.allocInfo.harqProcId = hqP->procId; +#endif + + pdcch->dci.u.format1Info.allocInfo.ndi = + rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.format1Info.allocInfo.mcs = + rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format1Info.allocInfo.rv = + rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; +#ifdef LTE_TDD + if(hqP->hqE->ue != NULLP) + { +#ifdef LTE_ADV + U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + hqP->hqE->ue); + + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),servCellIdx); +#else + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),0); +#endif +#ifdef TFU_TDD + if(anInfo) + { + pdcch->dci.u.format1Info.dai = RG_SCH_GET_DAI_VALUE(anInfo->dlDai); + } + else + { + /* Fixing DAI value - ccpu00109162 */ + pdcch->dci.u.format1Info.dai = RG_SCH_MAX_DAI_IDX; + } +#endif + } + else + { + /* always 0 for RACH */ + pdcch->dci.u.format1Info.allocInfo.harqProcId = 0; +#ifdef TFU_TDD + /* Fixing DAI value - ccpu00109162 */ + pdcch->dci.u.format1Info.dai = 1; +#endif + } +#endif + + + RETVOID; +} +/** + * @brief This function fills the PDCCH DCI format 1A information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt1A + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1A +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1A(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ + +#ifdef LTE_TDD + RgSchTddANInfo *anInfo; +#endif + +#ifdef LTEMAC_SPS + RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP); +#endif + + TRC2(rgSCHCmnFillHqPPdcchDciFrmt1A) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + pdcch->dci.u.format1aInfo.isPdcchOrder = FALSE; + pdcch->dci.u.format1aInfo.t.pdschInfo.tpcCmd = tpc; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.mcs = \ + rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.pres = TRUE; +#ifdef LTEMAC_SPS + if ((!(hqP->tbInfo[0].txCntr)) && + ( cmnHqDl != (RgSchCmnDlHqProc*)NULLP && + ((cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_ACTV) || + (cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_REACTV)) + )) + { + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.val = 0; + } + else + { + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.val + = hqP->procId; + } +#else + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.val = + hqP->procId; +#endif + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.ndi = \ + rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.rv = \ + rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + /* As of now, we do not support Distributed allocations */ + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.isLocal = TRUE; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.nGap2.pres = NOTPRSNT; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.alloc.type = + TFU_ALLOC_TYPE_RIV; + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.alloc.u.riv = + rgSCHCmnCalcRiv (cell->bwCfg.dlTotalBw, + rbAllocInfo->allocInfo.raType2.rbStart, + rbAllocInfo->allocInfo.raType2.numRb); +#ifdef LTE_TDD + if(hqP->hqE->ue != NULLP) + { +#ifdef LTE_ADV + U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + hqP->hqE->ue); + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),servCellIdx); +#else + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),0); +#endif +#ifdef TFU_TDD + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.pres = TRUE; + if(anInfo) + { + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.val = + RG_SCH_GET_DAI_VALUE(anInfo->dlDai); + } + else + { + /* Fixing DAI value - ccpu00109162 */ + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.val = RG_SCH_MAX_DAI_IDX; + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "PDCCH is been scheduled without updating anInfo RNTI:%d", + rbAllocInfo->rnti); + } +#endif + } + else + { + /* always 0 for RACH */ + pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.harqProcId.pres + = FALSE; +#ifdef TFU_TDD + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.pres = TRUE; + /* Fixing DAI value - ccpu00109162 */ + pdcch->dci.u.format1aInfo.t.pdschInfo.dai.val = 1; +#endif + } +#endif + + RETVOID; +} +/** + * @brief This function fills the PDCCH DCI format 1B information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt1B + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1B +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt1B(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ + +#ifdef LTE_TDD + RgSchTddANInfo *anInfo; +#endif + +#ifdef LTEMAC_SPS + RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP); +#endif + + TRC2(rgSCHCmnFillHqPPdcchDciFrmt1B) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + pdcch->dci.u.format1bInfo.tpcCmd = tpc; + pdcch->dci.u.format1bInfo.allocInfo.mcs = \ + rbAllocInfo->tbInfo[0].imcs; +#ifdef LTEMAC_SPS + if ((!(hqP->tbInfo[0].txCntr)) && + ( cmnHqDl != (RgSchCmnDlHqProc*)NULLP && + ((cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_ACTV) || + (cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_REACTV)) + )) + { + pdcch->dci.u.format1bInfo.allocInfo.harqProcId = 0; + } + else + { + pdcch->dci.u.format1bInfo.allocInfo.harqProcId = hqP->procId; + } +#else + pdcch->dci.u.format1bInfo.allocInfo.harqProcId = hqP->procId; +#endif + pdcch->dci.u.format1bInfo.allocInfo.ndi = \ + rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.format1bInfo.allocInfo.rv = \ + rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + /* As of now, we do not support Distributed allocations */ + pdcch->dci.u.format1bInfo.allocInfo.isLocal = TRUE; + pdcch->dci.u.format1bInfo.allocInfo.nGap2.pres = NOTPRSNT; + pdcch->dci.u.format1bInfo.allocInfo.alloc.type = + TFU_ALLOC_TYPE_RIV; + pdcch->dci.u.format1bInfo.allocInfo.alloc.u.riv = + rgSCHCmnCalcRiv (cell->bwCfg.dlTotalBw, + rbAllocInfo->allocInfo.raType2.rbStart, + rbAllocInfo->allocInfo.raType2.numRb); + /* Fill precoding Info */ + pdcch->dci.u.format1bInfo.allocInfo.pmiCfm = \ + rbAllocInfo->mimoAllocInfo.precIdxInfo >> 4; + pdcch->dci.u.format1bInfo.allocInfo.tPmi = \ + rbAllocInfo->mimoAllocInfo.precIdxInfo & 0x0F; +#ifdef LTE_TDD + if(hqP->hqE->ue != NULLP) + { +#ifdef LTE_ADV + U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + hqP->hqE->ue); + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),servCellIdx); +#else + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),0); +#endif +#ifdef TFU_TDD + if(anInfo) + { + pdcch->dci.u.format1bInfo.dai = + RG_SCH_GET_DAI_VALUE(anInfo->dlDai); + } + else + { + pdcch->dci.u.format1bInfo.dai = RG_SCH_MAX_DAI_IDX; + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "PDCCH is been scheduled without updating anInfo RNTI:%d", + rbAllocInfo->rnti); + } +#endif + } +#endif + + RETVOID; + +} +/** + * @brief This function fills the PDCCH DCI format 2 information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt2 + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2 +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ + +#ifdef LTE_TDD + RgSchTddANInfo *anInfo; +#endif + +#ifdef LTEMAC_SPS +/* ccpu00119023-ADD-For activation or reactivation, + * Harq ProcId should be 0 */ + RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP); +#endif + + TRC2(rgSCHCmnFillHqPPdcchDciFrmt2) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + /*ccpu00120365:-ADD-call also if tb is disabled */ + if (rbAllocInfo->tbInfo[1].schdlngForTb || + rbAllocInfo->tbInfo[1].isDisabled) + { + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 1, pdcch); + } + pdcch->dci.u.format2Info.tpcCmd = tpc; + /* Avoiding this check,as we dont support Type1 RA */ +#ifdef RG_UNUSED + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { +#endif + pdcch->dci.u.format2Info.allocInfo.isAllocType0 = TRUE; + pdcch->dci.u.format2Info.allocInfo.resAllocMap[0] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 24) + & 0xff); + pdcch->dci.u.format2Info.allocInfo.resAllocMap[1] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 16) + & 0x00ff); + pdcch->dci.u.format2Info.allocInfo.resAllocMap[2] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 8) + & 0x0000ff); + pdcch->dci.u.format2Info.allocInfo.resAllocMap[3] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask & 0x000000ff)); +#ifdef RG_UNUSED + } +#endif +#ifdef LTEMAC_SPS + if ((!(hqP->tbInfo[0].txCntr)) && + ( cmnHqDl != (RgSchCmnDlHqProc*)NULLP && + ((cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_ACTV) || + (cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_REACTV)) + )) + { + pdcch->dci.u.format2Info.allocInfo.harqProcId = 0; + } + else + { + pdcch->dci.u.format2Info.allocInfo.harqProcId = hqP->procId; + } +#else + pdcch->dci.u.format2Info.allocInfo.harqProcId = hqP->procId; +#endif + /* Initialize the TB info for both the TBs */ + pdcch->dci.u.format2Info.allocInfo.tbInfo[0].mcs = 0; + pdcch->dci.u.format2Info.allocInfo.tbInfo[0].rv = 1; + pdcch->dci.u.format2Info.allocInfo.tbInfo[1].mcs = 0; + pdcch->dci.u.format2Info.allocInfo.tbInfo[1].rv = 1; + /* Fill tbInfo for scheduled TBs */ + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].ndi = rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].rv = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + /* If we reach this function. It is safely assumed that + * rbAllocInfo->tbInfo[0] always has non default valid values. + * rbAllocInfo->tbInfo[1]'s scheduling is optional */ + if (rbAllocInfo->tbInfo[1].schdlngForTb == TRUE) + { + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].ndi = rbAllocInfo->tbInfo[1].tbCb->ndi; + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].mcs = rbAllocInfo->tbInfo[1].imcs; + pdcch->dci.u.format2Info.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].rv = rbAllocInfo->tbInfo[1].tbCb->dlGrnt.rv; + } + pdcch->dci.u.format2Info.allocInfo.transSwap = + rbAllocInfo->mimoAllocInfo.swpFlg; + pdcch->dci.u.format2Info.allocInfo.precoding = + rbAllocInfo->mimoAllocInfo.precIdxInfo; +#ifdef LTE_TDD + if(hqP->hqE->ue != NULLP) + { + +#ifdef LTE_ADV + U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + hqP->hqE->ue); + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),servCellIdx); +#else + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),0); +#endif +#ifdef TFU_TDD + if(anInfo) + { + pdcch->dci.u.format2Info.dai = RG_SCH_GET_DAI_VALUE(anInfo->dlDai); + } + else + { + pdcch->dci.u.format2Info.dai = RG_SCH_MAX_DAI_IDX; + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "PDCCH is been scheduled without updating anInfo RNTI:%d", + rbAllocInfo->rnti); + } +#endif + } +#endif + + RETVOID; +} +/** + * @brief This function fills the PDCCH DCI format 2A information from dlProc. + * + * @details + * + * Function: rgSCHCmnFillHqPPdcchDciFrmt2A + * Purpose: This function fills in the PDCCH information + * obtained from the RgSchDlHqProcCb and RgSchDlRbAlloc + * for dedicated service scheduling. It also + * obtains TPC to be filled in from the power module. + * Assign the PDCCH to HQProc. + * + * Invoked by: Downlink Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlRbAlloc* rbAllocInfo + * @param[in] RgDlHqProc* hqP + * @param[out] RgSchPdcch *pdcch + * @param[in] U8 tpc + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2A +( +RgSchCellCb *cell, +RgSchDlRbAlloc *rbAllocInfo, +RgSchDlHqProcCb *hqP, +RgSchPdcch *pdcch, +U8 tpc +) +#else +PRIVATE Void rgSCHCmnFillHqPPdcchDciFrmt2A(cell, rbAllocInfo, hqP, pdcch, tpc) +RgSchCellCb *cell; +RgSchDlRbAlloc *rbAllocInfo; +RgSchDlHqProcCb *hqP; +RgSchPdcch *pdcch; +U8 tpc; +#endif +{ +#ifdef LTE_TDD + RgSchTddANInfo *anInfo; +#endif + +#ifdef LTEMAC_SPS + RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP); +#endif + + TRC2(rgSCHCmnFillHqPPdcchDciFrmt2A) + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 0, pdcch); + /*ccpu00120365:-ADD-call also if tb is disabled */ + if (rbAllocInfo->tbInfo[1].schdlngForTb || + rbAllocInfo->tbInfo[1].isDisabled) + { + + rgSCHCmnFillHqPTb(cell, rbAllocInfo, 1, pdcch); + } + + pdcch->dci.u.format2AInfo.tpcCmd = tpc; + /* Avoiding this check,as we dont support Type1 RA */ +#ifdef RG_UNUSED + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { +#endif + pdcch->dci.u.format2AInfo.allocInfo.isAllocType0 = TRUE; + pdcch->dci.u.format2AInfo.allocInfo.resAllocMap[0] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 24) + & 0xff); + pdcch->dci.u.format2AInfo.allocInfo.resAllocMap[1] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 16) + & 0x00ff); + pdcch->dci.u.format2AInfo.allocInfo.resAllocMap[2] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask >> 8) + & 0x0000ff); + pdcch->dci.u.format2AInfo.allocInfo.resAllocMap[3] = + ((rbAllocInfo->allocInfo.raType0.dlAllocBitMask & 0x000000ff)); +#ifdef RG_UNUSED + } +#endif +#ifdef LTEMAC_SPS + if ((!(hqP->tbInfo[0].txCntr)) && + ( cmnHqDl != (RgSchCmnDlHqProc*)NULLP && + ((cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_ACTV) || + (cmnHqDl->spsAction & RG_SCH_CMN_SPS_DL_REACTV)) + )) + { + pdcch->dci.u.format2AInfo.allocInfo.harqProcId = 0; + } + else + { + pdcch->dci.u.format2AInfo.allocInfo.harqProcId = hqP->procId; + } +#else + pdcch->dci.u.format2AInfo.allocInfo.harqProcId = hqP->procId; +#endif + /* Initialize the TB info for both the TBs */ + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[0].mcs = 0; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[0].rv = 1; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[1].mcs = 0; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[1].rv = 1; + /* Fill tbInfo for scheduled TBs */ + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].ndi = rbAllocInfo->tbInfo[0].tbCb->ndi; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].mcs = rbAllocInfo->tbInfo[0].imcs; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[0].\ + tbCb->tbIdx].rv = rbAllocInfo->tbInfo[0].tbCb->dlGrnt.rv; + /* If we reach this function. It is safely assumed that + * rbAllocInfo->tbInfo[0] always has non default valid values. + * rbAllocInfo->tbInfo[1]'s scheduling is optional */ + + if (rbAllocInfo->tbInfo[1].schdlngForTb == TRUE) + { + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].ndi = rbAllocInfo->tbInfo[1].tbCb->ndi; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].mcs = rbAllocInfo->tbInfo[1].imcs; + pdcch->dci.u.format2AInfo.allocInfo.tbInfo[rbAllocInfo->tbInfo[1].\ + tbCb->tbIdx].rv = rbAllocInfo->tbInfo[1].tbCb->dlGrnt.rv; + + } + pdcch->dci.u.format2AInfo.allocInfo.transSwap = + rbAllocInfo->mimoAllocInfo.swpFlg; + pdcch->dci.u.format2AInfo.allocInfo.precoding = + rbAllocInfo->mimoAllocInfo.precIdxInfo; +#ifdef LTE_TDD + if(hqP->hqE->ue != NULLP) + { +#ifdef LTE_ADV + U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx, + hqP->hqE->cell->cellId, + hqP->hqE->ue); + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),servCellIdx); +#else + anInfo = rgSCHUtlGetUeANFdbkInfo(hqP->hqE->ue, + &(rbAllocInfo->tbInfo[0].tbCb->fdbkTime),0); +#endif +#ifdef TFU_TDD + if(anInfo) + { + pdcch->dci.u.format2AInfo.dai = RG_SCH_GET_DAI_VALUE(anInfo->dlDai); + } + else + { + pdcch->dci.u.format2AInfo.dai = RG_SCH_MAX_DAI_IDX; + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "PDCCH is been scheduled without updating anInfo RNTI:%d", + rbAllocInfo->rnti); + } +#endif + } +#endif + + + RETVOID; +} + +/** + * @brief init of Sch vars. + * + * @details + * + * Function: rgSCHCmnInitVars + Purpose: Initialization of various UL subframe indices + * + * @param[in] RgSchCellCb *cell + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnInitVars +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnInitVars(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + + TRC2(rgSCHCmnInitVars); + + cellUl->idx = RGSCH_INVALID_INFO; + cellUl->schdIdx = RGSCH_INVALID_INFO; + cellUl->schdHqProcIdx = RGSCH_INVALID_INFO; + cellUl->msg3SchdIdx = RGSCH_INVALID_INFO; +#ifdef EMTC_ENBLE + cellUl->emtcMsg3SchdIdx = RGSCH_INVALID_INFO; +#endif + cellUl->msg3SchdHqProcIdx = RGSCH_INVALID_INFO; + cellUl->rcpReqIdx = RGSCH_INVALID_INFO; + cellUl->hqFdbkIdx[0] = RGSCH_INVALID_INFO; + cellUl->hqFdbkIdx[1] = RGSCH_INVALID_INFO; + cellUl->reTxIdx[0] = RGSCH_INVALID_INFO; + cellUl->reTxIdx[1] = RGSCH_INVALID_INFO; + /* Stack Crash problem for TRACE5 Changes. Added the return below */ + RETVOID; + +} + +#ifndef LTE_TDD +/** + * @brief Updation of Sch vars per TTI. + * + * @details + * + * Function: rgSCHCmnUpdVars + * Purpose: Updation of Sch vars per TTI. + * + * @param[in] RgSchCellCb *cell + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUpdVars +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnUpdVars(cell) +RgSchCellCb *cell; +#endif +{ + CmLteTimingInfo timeInfo; + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + U16 idx; + + TRC2(rgSCHCmnUpdVars); + + idx = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe); + cellUl->idx = ((idx) % (RG_SCH_CMN_UL_NUM_SF)); +#ifdef UL_ADPT_DBG + printf("idx %d cellUl->idx %d RGSCH_NUM_SUB_FRAMES_5G %d time(%d %d) \n",idx,cellUl->idx ,RGSCH_NUM_SUB_FRAMES_5G,cell->crntTime.sfn,cell->crntTime.subframe); +#endif + /* Need to scheduler for after SCHED_DELTA */ + /* UL allocation has been advanced by 1 subframe + * so that we do not wrap around and send feedback + * before the data is even received by the PHY */ + /* Introduced timing delta for UL control */ + idx = (cellUl->idx + TFU_ULCNTRL_DLDELTA + RGSCH_PDCCH_PUSCH_DELTA); + cellUl->schdIdx = ((idx) % (RG_SCH_CMN_UL_NUM_SF)); + + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo, + TFU_ULCNTRL_DLDELTA + RGSCH_PDCCH_PUSCH_DELTA) + cellUl->schdHqProcIdx = rgSCHCmnGetUlHqProcIdx(&timeInfo, cell); + + /* ccpu00127193 filling schdTime for logging and enhancement purpose*/ + cellUl->schdTime = timeInfo; + + /* msg3 scheduling two subframes after general scheduling */ + idx = (cellUl->idx + RG_SCH_CMN_DL_DELTA + RGSCH_RARSP_MSG3_DELTA); + cellUl->msg3SchdIdx = ((idx) % (RG_SCH_CMN_UL_NUM_SF)); + + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo, + RG_SCH_CMN_DL_DELTA+ RGSCH_RARSP_MSG3_DELTA) + cellUl->msg3SchdHqProcIdx = rgSCHCmnGetUlHqProcIdx(&timeInfo, cell); + + idx = (cellUl->idx + TFU_RECPREQ_DLDELTA); + + cellUl->rcpReqIdx = ((idx) % (RG_SCH_CMN_UL_NUM_SF)); + + /* Downlink harq feedback is sometime after data reception / harq failure */ + /* Since feedback happens prior to scheduling being called, we add 1 to */ + /* take care of getting the correct subframe for feedback */ + idx = (cellUl->idx - TFU_CRCIND_ULDELTA + RG_SCH_CMN_UL_NUM_SF); +#ifdef UL_ADPT_DBG + printf("Finally setting cellUl->hqFdbkIdx[0] = %d TFU_CRCIND_ULDELTA %d RG_SCH_CMN_UL_NUM_SF %d\n",idx,TFU_CRCIND_ULDELTA,RG_SCH_CMN_UL_NUM_SF); +#endif + cellUl->hqFdbkIdx[0] = (idx % (RG_SCH_CMN_UL_NUM_SF)); + + idx = ((cellUl->schdIdx) % (RG_SCH_CMN_UL_NUM_SF)); + + cellUl->reTxIdx[0] = (U8) idx; +#ifdef UL_ADPT_DBG + printf("cellUl->hqFdbkIdx[0] %d cellUl->reTxIdx[0] %d \n",cellUl->hqFdbkIdx[0], cellUl->reTxIdx[0] ); +#endif + /* RACHO: update cmn sched specific RACH variables, + * mainly the prachMaskIndex */ + rgSCHCmnUpdRachParam(cell); + + RETVOID; +} +#endif + +#ifdef LTE_TDD + +/** + * @brief To get uplink subframe index associated with current PHICH + * transmission. + * + * @details + * + * Function: rgSCHCmnGetPhichUlSfIdx + * Purpose: Gets uplink subframe index associated with current PHICH + * transmission based on SFN and subframe no + * + * @param[in] CmLteTimingInfo *timeInfo + * @param[in] RgSchCellCb *cell + * @return U8 + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnGetPhichUlSfIdx +( +CmLteTimingInfo *timeInfo, +RgSchCellCb *cell +) +#else +PUBLIC U8 rgSCHCmnGetPhichUlSfIdx(timeInfo, cell) +CmLteTimingInfo *timeInfo; +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchDlSf *dlsf; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 idx; + U16 numUlSf; + U16 sfn; + U8 subframe; + + TRC2(rgSCHCmnGetPhichUlSfIdx); + + dlsf = rgSCHUtlSubFrmGet(cell, *timeInfo); + + if(dlsf->phichOffInfo.sfnOffset == RGSCH_INVALID_INFO) + { + RETVALUE(RGSCH_INVALID_INFO); + } + subframe = dlsf->phichOffInfo.subframe; + + sfn = (RGSCH_MAX_SFN + timeInfo->sfn - + dlsf->phichOffInfo.sfnOffset) % RGSCH_MAX_SFN; + + /* ccpu00130980: numUlSf(U16) parameter added to avoid integer + * wrap case such that idx will be proper*/ + numUlSf = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + numUlSf = ((numUlSf * sfn) + rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][subframe]) - 1; + idx = numUlSf % (cellUl->numUlSubfrms); + + RETVALUE(idx); +} + +/** + * @brief To get uplink subframe index. + * + * @details + * + * + * Function: rgSCHCmnGetUlSfIdx + * Purpose: Gets uplink subframe index based on SFN and subframe number. + * + * @param[in] CmLteTimingInfo *timeInfo + * @param[in] U8 ulDlCfgIdx + * @return U8 + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnGetUlSfIdx +( +CmLteTimingInfo *timeInfo, +RgSchCellCb *cell +) +#else +PUBLIC U8 rgSCHCmnGetUlSfIdx(timeInfo, cell) +CmLteTimingInfo *timeInfo; +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 idx = 0; + U16 numUlSf; + + TRC2(rgSCHCmnGetUlSfIdx); + + /* ccpu00130980: numUlSf(U16) parameter added to avoid integer + * wrap case such that idx will be proper*/ + numUlSf = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + numUlSf = ((numUlSf * timeInfo->sfn) + \ + rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][timeInfo->subframe]) - 1; + idx = numUlSf % (cellUl->numUlSubfrms); + + RETVALUE(idx); +} + +#endif + +/** + * @brief To get uplink hq index. + * + * @details + * + * + * Function: rgSCHCmnGetUlHqProcIdx + * Purpose: Gets uplink subframe index based on SFN and subframe number. + * + * @param[in] CmLteTimingInfo *timeInfo + * @param[in] U8 ulDlCfgIdx + * @return U8 + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnGetUlHqProcIdx +( +CmLteTimingInfo *timeInfo, +RgSchCellCb *cell +) +#else +PUBLIC U8 rgSCHCmnGetUlHqProcIdx(timeInfo, cell) +CmLteTimingInfo *timeInfo; +RgSchCellCb *cell; +#endif +{ + U8 procId; + U32 numUlSf; + +#ifndef LTE_TDD + numUlSf = (timeInfo->sfn * RGSCH_NUM_SUB_FRAMES_5G + timeInfo->subframe); + procId = numUlSf % RGSCH_NUM_UL_HQ_PROC; +#else + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + /*ccpu00130639 - MOD - To get correct UL HARQ Proc IDs for all UL/DL Configs*/ + U8 numUlSfInSfn; + S8 sfnCycle = cell->tddHqSfnCycle; + U8 numUlHarq = rgSchTddUlNumHarqProcTbl[ulDlCfgIdx] + + /* TRACE 5 Changes */ + TRC2(rgSCHCmnGetUlHqProcIdx); + + /* Calculate the number of UL SF in one SFN */ + numUlSfInSfn = RGSCH_NUM_SUB_FRAMES - + rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + + /* Check for the SFN wrap around case */ + if(cell->crntTime.sfn == 1023 && timeInfo->sfn == 0) + { + sfnCycle++; + } + else if(cell->crntTime.sfn == 0 && timeInfo->sfn == 1023) + { + /* sfnCycle decremented by 1 */ + sfnCycle = (sfnCycle + numUlHarq-1) % numUlHarq; + } + /* Calculate the total number of UL sf */ + /* -1 is done since uplink sf are counted from 0 */ + numUlSf = numUlSfInSfn * (timeInfo->sfn + (sfnCycle*1024)) + + rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][timeInfo->subframe] - 1; + + procId = numUlSf % numUlHarq; +#endif + RETVALUE(procId); +} + + +/* UL_ALLOC_CHANGES */ +/*********************************************************** + * + * Func : rgSCHCmnUlFreeAlloc + * + * Desc : Free an allocation - invokes UHM and releases + * alloc for the scheduler + * Doest need subframe as argument + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlFreeAlloc +( +RgSchCellCb *cell, +RgSchUlAlloc *alloc +) +#else +PUBLIC Void rgSCHCmnUlFreeAlloc(cell, alloc) +RgSchCellCb *cell; +RgSchUlAlloc *alloc; +#endif +{ + RgSchUlHqProcCb *hqProc; + TRC2(rgSCHCmnUlFreeAllocation); + + if (alloc->forMsg3) + { + /* Fix : Release RNTI upon MSG3 max TX failure for non-HO UEs */ + if ((alloc->hqProc->remTx == 0) && + (alloc->hqProc->rcvdCrcInd == FALSE) && + (alloc->raCb)) + { + RgSchRaCb *raCb = alloc->raCb; + rgSCHUhmFreeProc(alloc->hqProc, cell); + rgSCHUtlUlAllocRelease(alloc); + rgSCHRamDelRaCb(cell, raCb, TRUE); + RETVOID; + } + } + + hqProc = alloc->hqProc; + rgSCHUtlUlAllocRelease(alloc); + rgSCHUhmFreeProc(hqProc, cell); + RETVOID; +} + + +/*********************************************************** + * + * Func : rgSCHCmnUlFreeAllocation + * + * Desc : Free an allocation - invokes UHM and releases + * alloc for the scheduler + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlFreeAllocation +( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUlAlloc *alloc +) +#else +PUBLIC Void rgSCHCmnUlFreeAllocation(cell, sf, alloc) +RgSchCellCb *cell; +RgSchUlSf *sf; +RgSchUlAlloc *alloc; +#endif +{ + RgSchUlHqProcCb *hqProc; + + TRC2(rgSCHCmnUlFreeAllocation); + + if (alloc->forMsg3) + { + /* Fix : Release RNTI upon MSG3 max TX failure for non-HO UEs */ + if ((alloc->hqProc->remTx == 0) && + (alloc->hqProc->rcvdCrcInd == FALSE) && + (alloc->raCb)) + { + RgSchRaCb *raCb = alloc->raCb; + rgSCHUhmFreeProc(alloc->hqProc, cell); + rgSCHUtlUlAllocRls(sf, alloc); + rgSCHRamDelRaCb(cell, raCb, TRUE); + RETVOID; + } + } + + hqProc = alloc->hqProc; + rgSCHUhmFreeProc(hqProc, cell); +#ifdef LTE_L2_MEAS + /* re-setting the PRB count while freeing the allocations */ + sf->totPrb = 0; +#endif + rgSCHUtlUlAllocRls(sf, alloc); + + RETVOID; +} + +/** + * @brief This function implements PDCCH allocation for an UE + * in the currently running subframe. + * + * @details + * + * Function: rgSCHCmnPdcchAllocCrntSf + * Purpose: This function determines current DL subframe + * and UE DL CQI to call the actual pdcch allocator + * function. + * Note that this function is called only + * when PDCCH request needs to be made during + * uplink scheduling. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return RgSchPdcch * + * -# NULLP when unsuccessful + **/ +#ifdef ANSI +PUBLIC RgSchPdcch *rgSCHCmnPdcchAllocCrntSf +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC RgSchPdcch *rgSCHCmnPdcchAllocCrntSf(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + CmLteTimingInfo frm = cell->crntTime; + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgSchDlSf *sf; + RgSchPdcch *pdcch = NULLP; + + TRC2(rgSCHCmnPdcchAllocCrntSf); + RGSCH_INCR_SUB_FRAME(frm, TFU_ULCNTRL_DLDELTA); + sf = rgSCHUtlSubFrmGet(cell, frm); + +#ifdef LTE_ADV + if (ue->allocCmnUlPdcch) + { + pdcch = rgSCHCmnCmnPdcchAlloc(cell, sf); + /* Since CRNTI Scrambled */ + if(NULLP != pdcch) + { + pdcch->dciNumOfBits = ue->dciSize.cmnSize[TFU_DCI_FORMAT_0]; + } + } + else +#endif + { + //pdcch = rgSCHCmnPdcchAlloc(cell, ue, sf, y, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_0, FALSE); + pdcch = rgSCHCmnPdcchAlloc(cell, ue, sf, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_A1, FALSE); + } + RETVALUE(pdcch); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlAllocFillNdmrs + * + * Desc : Determines and fills N_dmrs for a UE uplink + * allocation. + * + * Ret : + * + * Notes: N_dmrs determination is straightforward, so + * it is configured per subband + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAllocFillNdmrs +( +RgSchCmnUlCell *cellUl, +RgSchUlAlloc *alloc +) +#else +PUBLIC Void rgSCHCmnUlAllocFillNdmrs(cellUl, alloc) +RgSchCmnUlCell *cellUl; +RgSchUlAlloc *alloc; +#endif +{ + TRC2(rgSCHCmnUlAllocFillNdmrs); + alloc->grnt.nDmrs = cellUl->dmrsArr[alloc->sbStart]; + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnUlAllocLnkHqProc + * + * Desc : Links a new allocation for an UE with the + * appropriate HARQ process of the UE. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAllocLnkHqProc +( +RgSchUeCb *ue, +RgSchUlAlloc *alloc, +RgSchUlHqProcCb *proc, +Bool isRetx +) +#else +PUBLIC Void rgSCHCmnUlAllocLnkHqProc(ue, alloc, proc, isRetx) +RgSchUeCb *ue; +RgSchUlAlloc *alloc; +RgSchUlHqProcCb *proc; +Bool isRetx; +#endif +{ + TRC2(rgSCHCmnUlAllocLnkHqProc); + + if(TRUE == isRetx) + { + rgSCHCmnUlAdapRetx(alloc, proc); + } + else + { +#ifdef LTE_L2_MEAS /* L2_COUNTERS */ + alloc->ue = ue; +#endif + rgSCHUhmNewTx(proc, (((RgUeUlHqCb*)proc->hqEnt)->maxHqRetx), alloc); + } + RETVOID; +} + +/** + * @brief This function releases a PDCCH in the subframe that is + * currently being allocated for. + * + * @details + * + * Function: rgSCHCmnPdcchRlsCrntSf + * Purpose: This function determines current DL subframe + * which is considered for PDCCH allocation, + * and then calls the actual function that + * releases a PDCCH in a specific subframe. + * Note that this function is called only + * when PDCCH release needs to be made during + * uplink scheduling. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchPdcch *pdcch + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnPdcchRlsCrntSf +( +RgSchCellCb *cell, +RgSchPdcch *pdcch +) +#else +PUBLIC Void rgSCHCmnPdcchRlsCrntSf(cell, pdcch) +RgSchCellCb *cell; +RgSchPdcch *pdcch; +#endif +{ + CmLteTimingInfo frm = cell->crntTime; + RgSchDlSf *sf; + + TRC2(rgSCHCmnPdcchRlsCrntSf); + + RGSCH_INCR_SUB_FRAME(frm, TFU_ULCNTRL_DLDELTA); + sf = rgSCHUtlSubFrmGet(cell, frm); + rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, pdcch); + RETVOID; +} +/*********************************************************** + * + * Func : rgSCHCmnUlFillPdcchWithAlloc + * + * Desc : Fills a PDCCH with format 0 information. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlFillPdcchWithAlloc +( +RgSchPdcch *pdcch, +RgSchUlAlloc *alloc, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlFillPdcchWithAlloc(pdcch, alloc, ue) +RgSchPdcch *pdcch; +RgSchUlAlloc *alloc; +RgSchUeCb *ue; +#endif +{ + + TRC2(rgSCHCmnUlFillPdcchWithAlloc); + + pdcch->ue = ue; + pdcch->rnti = alloc->rnti; + //pdcch->dci.dciFormat = TFU_DCI_FORMAT_A2; + pdcch->dci.dciFormat = alloc->grnt.dciFrmt; + + //Currently hardcoding values here. + //printf("Filling 5GTF UL DCI for rnti %d \n",alloc->rnti); + switch(pdcch->dci.dciFormat) + { + case TFU_DCI_FORMAT_A1: + { + pdcch->dci.u.formatA1Info.formatType = 0; + pdcch->dci.u.formatA1Info.xPUSCHRange = alloc->grnt.xPUSCHRange; + pdcch->dci.u.formatA1Info.xPUSCH_TxTiming = 0; + pdcch->dci.u.formatA1Info.RBAssign = alloc->grnt.rbAssign; + pdcch->dci.u.formatA1Info.u.rbAssignA1Val324.hqProcId = alloc->grnt.hqProcId; + pdcch->dci.u.formatA1Info.u.rbAssignA1Val324.mcs = alloc->grnt.iMcsCrnt; + pdcch->dci.u.formatA1Info.u.rbAssignA1Val324.ndi = alloc->hqProc->ndi; + pdcch->dci.u.formatA1Info.CSI_BSI_BRI_Req = 0; + pdcch->dci.u.formatA1Info.CSIRS_BRRS_TxTiming = 0; + pdcch->dci.u.formatA1Info.CSIRS_BRRS_SymbIdx = 0; + pdcch->dci.u.formatA1Info.CSIRS_BRRS_ProcInd = 0; + pdcch->dci.u.formatA1Info.numBSI_Reports = 0; + pdcch->dci.u.formatA1Info.uciOnxPUSCH = alloc->grnt.uciOnxPUSCH; + pdcch->dci.u.formatA1Info.beamSwitch = 0; + pdcch->dci.u.formatA1Info.SRS_Config = 0; + pdcch->dci.u.formatA1Info.SRS_Symbol = 0; + pdcch->dci.u.formatA1Info.REMapIdx_DMRS_PCRS_numLayers = 0; + pdcch->dci.u.formatA1Info.SCID = alloc->grnt.SCID; + pdcch->dci.u.formatA1Info.PMI = alloc->grnt.PMI; + pdcch->dci.u.formatA1Info.UL_PCRS = 0; + pdcch->dci.u.formatA1Info.tpcCmd = alloc->grnt.tpc; + break; + } + case TFU_DCI_FORMAT_A2: + { + pdcch->dci.u.formatA2Info.formatType = 1; + pdcch->dci.u.formatA2Info.xPUSCHRange = alloc->grnt.xPUSCHRange; + pdcch->dci.u.formatA2Info.xPUSCH_TxTiming = 0; + pdcch->dci.u.formatA2Info.RBAssign = alloc->grnt.rbAssign; + pdcch->dci.u.formatA2Info.u.rbAssignA1Val324.hqProcId = alloc->grnt.hqProcId; + pdcch->dci.u.formatA2Info.u.rbAssignA1Val324.mcs = alloc->grnt.iMcsCrnt; + pdcch->dci.u.formatA2Info.u.rbAssignA1Val324.ndi = alloc->hqProc->ndi; + pdcch->dci.u.formatA2Info.CSI_BSI_BRI_Req = 0; + pdcch->dci.u.formatA2Info.CSIRS_BRRS_TxTiming = 0; + pdcch->dci.u.formatA2Info.CSIRS_BRRS_SymbIdx = 0; + pdcch->dci.u.formatA2Info.CSIRS_BRRS_ProcInd = 0; + pdcch->dci.u.formatA2Info.numBSI_Reports = 0; + pdcch->dci.u.formatA2Info.uciOnxPUSCH = alloc->grnt.uciOnxPUSCH; + pdcch->dci.u.formatA2Info.beamSwitch = 0; + pdcch->dci.u.formatA2Info.SRS_Config = 0; + pdcch->dci.u.formatA2Info.SRS_Symbol = 0; + pdcch->dci.u.formatA2Info.REMapIdx_DMRS_PCRS_numLayers = 0; + pdcch->dci.u.formatA2Info.SCID = alloc->grnt.SCID; + pdcch->dci.u.formatA2Info.PMI = alloc->grnt.PMI; + pdcch->dci.u.formatA2Info.UL_PCRS = 0; + pdcch->dci.u.formatA2Info.tpcCmd = alloc->grnt.tpc; + break; + } + default: + RLOG1(L_ERROR," 5GTF_ERROR UL Allocator's icorrect " + "dciForamt Fill RNTI:%d",alloc->rnti); + break; + } + + + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnUlAllocFillTpc + * + * Desc : Determines and fills TPC for an UE allocation. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAllocFillTpc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchUlAlloc *alloc +) +#else +PUBLIC Void rgSCHCmnUlAllocFillTpc(cell, ue, alloc) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchUlAlloc *alloc; +#endif +{ + TRC2(rgSCHCmnUlAllocFillTpc); + alloc->grnt.tpc = rgSCHPwrPuschTpcForUe(cell, ue); + RETVOID; +} + + +/*********************************************************** + * + * Func : rgSCHCmnAddUeToRefreshQ + * + * Desc : Adds a UE to refresh queue, so that the UE is + * periodically triggered to refresh it's GBR and + * AMBR values. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnAddUeToRefreshQ +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 wait +) +#else +PRIVATE Void rgSCHCmnAddUeToRefreshQ(cell, ue, wait) +RgSchCellCb *cell; +RgSchUeCb *ue; +U32 wait; +#endif +{ + RgSchCmnCell *sched = RG_SCH_CMN_GET_CELL(cell); + CmTmrArg arg; + RgSchCmnUeInfo *ueSchd = RG_SCH_CMN_GET_CMN_UE(ue); + + TRC2(rgSCHCmnAddUeToRefreshQ); + UNUSED(cell); + + cmMemset((U8 *)&arg, 0, sizeof(arg)); + arg.tqCp = &sched->tmrTqCp; + arg.tq = sched->tmrTq; + arg.timers = &ueSchd->tmr; + arg.cb = (PTR)ue; + arg.tNum = 0; + arg.max = 1; + arg.evnt = RG_SCH_CMN_EVNT_UE_REFRESH; + arg.wait = wait; + cmPlcCbTq(&arg); + RETVOID; +} + +/** + * @brief Perform UE reset procedure. + * + * @details + * + * Function : rgSCHCmnUlUeReset + * + * This functions performs BSR resetting and + * triggers UL specific scheduler + * to Perform UE reset procedure. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlUeReset +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnUlUeReset(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + U8 lcgCnt=0; + RgSchCmnLcg *lcgCmn; + CmLList *node; + RgSchCmnAllocRecord *allRcd; + TRC2(rgSCHCmnUlUeReset); + + ue->ul.minReqBytes = 0; + ue->ul.totalBsr = 0; + ue->ul.effBsr = 0; + ue->ul.nonGbrLcgBs = 0; + ue->ul.effAmbr = ue->ul.cfgdAmbr; + + node = ueUl->ulAllocLst.first; + while (node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + allRcd->alloc = 0; + node = node->next; + } + for(lcgCnt = 0; lcgCnt < RGSCH_MAX_LCG_PER_UE; lcgCnt++) + { + lcgCmn = RG_SCH_CMN_GET_UL_LCG(&ue->ul.lcgArr[lcgCnt]); + lcgCmn->bs = 0; + lcgCmn->reportedBs = 0; + lcgCmn->effGbr = lcgCmn->cfgdGbr; + lcgCmn->effDeltaMbr = lcgCmn->deltaMbr; + } + rgSCHCmnUlUeDelAllocs(cell, ue); + + ue->isSrGrant = FALSE; + + cellSchd->apisUl->rgSCHUlUeReset(cell, ue); + + /* Stack Crash problem for TRACE5 changes. Added the return below */ + RETVOID; + +} + +/** + * @brief RESET UL CQI and DL CQI&RI to conservative values + * for a reestablishing UE. + * + * @details + * + * Function : rgSCHCmnResetRiCqi + * + * RESET UL CQI and DL CQI&RI to conservative values + * for a reestablishing UE + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnResetRiCqi +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnResetRiCqi(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue,cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + + TRC2(rgSCHCmnResetRiCqi); + + rgSCHCmnUpdUeUlCqiInfo(cell, ue, ueUl, ueSchCmn, cellSchd, + cell->isCpUlExtend); + + ueDl->mimoInfo.cwInfo[0].cqi = cellSchd->dl.ccchCqi; + ueDl->mimoInfo.cwInfo[1].cqi = cellSchd->dl.ccchCqi; + ueDl->mimoInfo.ri = 1; + if ((ue->mimoInfo.txMode == RGR_UE_TM_4) || + (ue->mimoInfo.txMode == RGR_UE_TM_6)) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_NO_PMI); + } + if (ue->mimoInfo.txMode == RGR_UE_TM_3) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } +#ifdef EMTC_ENABLE + rgSCHCmnDlSetUeAllocLmt(cell, ueDl, ue->isEmtcUe); +#else + rgSCHCmnDlSetUeAllocLmt(cell, ueDl, FALSE); +#endif + +#ifdef TFU_UPGRADE + /* Request for an early Aper CQI in case of reest */ + RgSchUeACqiCb *acqiCb = RG_SCH_CMN_GET_ACQICB(ue,cell); + if(acqiCb && acqiCb->aCqiCfg.pres) + { + acqiCb->aCqiTrigWt = 0; + } +#endif + + RETVOID; +} + +/** + * @brief Perform UE reset procedure. + * + * @details + * + * Function : rgSCHCmnDlUeReset + * + * This functions performs BO resetting and + * triggers DL specific scheduler + * to Perform UE reset procedure. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlUeReset +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnDlUeReset(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnDlUeReset); + + if (ueDl->rachInfo.poLnk.node != NULLP) + { + rgSCHCmnDlRmvFrmPdcchOdrQ(cell, ue); + } + + /* Fix: syed Remove from TA List if this UE is there. + * If TA Timer is running. Stop it */ + if (ue->dlTaLnk.node) + { + cmLListDelFrm(&cellCmnDl->taLst, &ue->dlTaLnk); + ue->dlTaLnk.node = (PTR)NULLP; + } + else if (ue->taTmr.tmrEvnt != TMR_NONE) + { + rgSCHTmrStopTmr(cell, ue->taTmr.tmrEvnt, ue); + } + + cellSchd->apisDl->rgSCHDlUeReset(cell, ue); +#ifdef LTE_ADV + if (ue->numSCells) + { + rgSCHSCellDlUeReset(cell,ue); + } +#endif +} + +/** + * @brief Perform UE reset procedure. + * + * @details + * + * Function : rgSCHCmnUeReset + * + * This functions triggers specific scheduler + * to Perform UE reset procedure. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUeReset +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUeReset(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + U8 idx; + Pst pst; + RgInfResetHqEnt hqEntRstInfo; + + TRC2(rgSCHCmnUeReset); + /* RACHO: remove UE from pdcch, handover and rapId assoc Qs */ + rgSCHCmnDelRachInfo(cell, ue); + + rgSCHPwrUeReset(cell, ue); + + rgSCHCmnUlUeReset(cell, ue); + rgSCHCmnDlUeReset(cell, ue); + +#ifdef LTE_ADV + /* Making allocCmnUlPdcch TRUE to allocate DCI0/1A from Common search space. + As because multiple cells are added hence 2 bits CqiReq is there + This flag will be set to FALSE once we will get Scell READY */ + ue->allocCmnUlPdcch = TRUE; +#endif + + /* Fix : syed RESET UL CQI and DL CQI&RI to conservative values + * for a reestablishing UE */ + /*Reset Cqi Config for all the configured cells*/ + for (idx = 0;idx < CM_LTE_MAX_CELLS; idx++) + { + if (ue->cellInfo[idx] != NULLP) + { + rgSCHCmnResetRiCqi(ue->cellInfo[idx]->cell, ue); + } + } + /*After Reset Trigger APCQI for Pcell*/ + RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ue); + if(pCellInfo->acqiCb.aCqiCfg.pres) + { + ue->dl.reqForCqi = RG_SCH_APCQI_SERVING_CC; + } + +/* sending HqEnt reset to MAC */ + hqEntRstInfo.cellId = cell->cellId; + hqEntRstInfo.crnti = ue->ueId; + + rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst); + RgSchMacRstHqEnt(&pst,&hqEntRstInfo); + + RETVOID; +} + +/** + * @brief UE out of MeasGap or AckNackReptn. + * + * @details + * + * Function : rgSCHCmnActvtUlUe + * + * This functions triggers specific scheduler + * to start considering it for scheduling. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnActvtUlUe +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnActvtUlUe(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnActvtUlUe); + + /* : take care of this in UL retransmission */ + cellSchd->apisUl->rgSCHUlActvtUe(cell, ue); + RETVOID; +} + +/** + * @brief UE out of MeasGap or AckNackReptn. + * + * @details + * + * Function : rgSCHCmnActvtDlUe + * + * This functions triggers specific scheduler + * to start considering it for scheduling. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnActvtDlUe +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnActvtDlUe(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnActvtDlUe); + + cellSchd->apisDl->rgSCHDlActvtUe(cell, ue); + RETVOID; +} + +/** + * @brief This API is invoked to indicate scheduler of a CRC indication. + * + * @details + * + * Function : rgSCHCmnHdlUlTransInd + * This API is invoked to indicate scheduler of a CRC indication. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] CmLteTimingInfo timingInfo + * + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnHdlUlTransInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteTimingInfo timingInfo +) +#else +PUBLIC Void rgSCHCmnHdlUlTransInd(cell, ue, timingInfo) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteTimingInfo timingInfo; +#endif +{ + TRC2(rgSCHCmnHdlUlTransInd); + + /* Update the latest UL dat/sig transmission time */ + RGSCHCPYTIMEINFO(timingInfo, ue->ul.ulTransTime); + if (RG_SCH_CMN_IS_UE_PDCCHODR_INACTV(ue)) + { + /* Some UL Transmission from this UE. + * Activate this UE if it was inactive */ + RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_PDCCHODR_INACTIVE); + RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_PDCCHODR_INACTIVE); + } + RETVOID; +} + +#ifdef TFU_UPGRADE + +/** + * @brief Compute the minimum Rank based on Codebook subset + * restriction configuration for 4 Tx Ports and Tx Mode 4. + * + * @details + * + * Function : rgSCHCmnComp4TxMode4 + * + * Depending on BitMap set at CBSR during Configuration + * - return the least possible Rank + * + * + * @param[in] U32 *pmiBitMap + * @return RgSchCmnRank + **/ +#ifdef ANSI +PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode4 +( + U32 *pmiBitMap + ) +#else +PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode4(pmiBitMap) + U32 *pmiBitMap; +#endif +{ + U32 bitMap0, bitMap1; + TRC2(rgSCHCmnComp4TxMode4); + bitMap0 = pmiBitMap[0]; + bitMap1 = pmiBitMap[1]; + if((bitMap1) & 0xFFFF) + { + RETVALUE (RG_SCH_CMN_RANK_1); + } + else if((bitMap1>>16) & 0xFFFF) + { + RETVALUE (RG_SCH_CMN_RANK_2); + } + else if((bitMap0) & 0xFFFF) + { + RETVALUE (RG_SCH_CMN_RANK_3); + } + else if((bitMap0>>16) & 0xFFFF) + { + RETVALUE (RG_SCH_CMN_RANK_4); + } + else + { + RETVALUE (RG_SCH_CMN_RANK_1); + } +} + + +/** + * @brief Compute the minimum Rank based on Codebook subset + * restriction configuration for 2 Tx Ports and Tx Mode 4. + * + * @details + * + * Function : rgSCHCmnComp2TxMode4 + * + * Depending on BitMap set at CBSR during Configuration + * - return the least possible Rank + * + * + * @param[in] U32 *pmiBitMap + * @return RgSchCmnRank + **/ +#ifdef ANSI +PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode4 +( + U32 *pmiBitMap + ) +#else +PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode4(pmiBitMap) + U32 *pmiBitMap; +#endif +{ + U32 bitMap0; + TRC2(rgSCHCmnComp2TxMode4); + bitMap0 = pmiBitMap[0]; + if((bitMap0>>26)& 0x0F) + { + RETVALUE (RG_SCH_CMN_RANK_1); + } + else if((bitMap0>>30) & 3) + { + RETVALUE (RG_SCH_CMN_RANK_2); + } + else + { + RETVALUE (RG_SCH_CMN_RANK_1); + } +} + +/** + * @brief Compute the minimum Rank based on Codebook subset + * restriction configuration for 4 Tx Ports and Tx Mode 3. + * + * @details + * + * Function : rgSCHCmnComp4TxMode3 + * + * Depending on BitMap set at CBSR during Configuration + * - return the least possible Rank + * + * + * @param[in] U32 *pmiBitMap + * @return RgSchCmnRank + **/ +#ifdef ANSI +PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode3 +( + U32 *pmiBitMap + ) +#else +PRIVATE RgSchCmnRank rgSCHCmnComp4TxMode3(pmiBitMap) + U32 *pmiBitMap; +#endif +{ + U32 bitMap0; + TRC2(rgSCHCmnComp4TxMode3); + bitMap0 = pmiBitMap[0]; + if((bitMap0>>28)& 1) + { + RETVALUE (RG_SCH_CMN_RANK_1); + } + else if((bitMap0>>29) &1) + { + RETVALUE (RG_SCH_CMN_RANK_2); + } + else if((bitMap0>>30) &1) + { + RETVALUE (RG_SCH_CMN_RANK_3); + } + else if((bitMap0>>31) &1) + { + RETVALUE (RG_SCH_CMN_RANK_4); + } + else + { + RETVALUE (RG_SCH_CMN_RANK_1); + } +} + +/** + * @brief Compute the minimum Rank based on Codebook subset + * restriction configuration for 2 Tx Ports and Tx Mode 3. + * + * @details + * + * Function : rgSCHCmnComp2TxMode3 + * + * Depending on BitMap set at CBSR during Configuration + * - return the least possible Rank + * + * + * @param[in] U32 *pmiBitMap + * @return RgSchCmnRank + **/ +#ifdef ANSI +PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode3 +( + U32 *pmiBitMap + ) +#else +PRIVATE RgSchCmnRank rgSCHCmnComp2TxMode3(pmiBitMap) + U32 *pmiBitMap; +#endif +{ + U32 bitMap0; + TRC2(rgSCHCmnComp2TxMode3); + bitMap0 = pmiBitMap[0]; + if((bitMap0>>30)& 1) + { + RETVALUE (RG_SCH_CMN_RANK_1); + } + else if((bitMap0>>31) &1) + { + RETVALUE (RG_SCH_CMN_RANK_2); + } + else + { + RETVALUE (RG_SCH_CMN_RANK_1); + } +} + +/** + * @brief Compute the minimum Rank based on Codebook subset + * restriction configuration. + * + * @details + * + * Function : rgSCHCmnComputeRank + * + * Depending on Num Tx Ports and Transmission mode + * - return the least possible Rank + * + * + * @param[in] RgrTxMode txMode + * @param[in] U32 *pmiBitMap + * @param[in] U8 numTxPorts + * @return RgSchCmnRank + **/ +#ifdef ANSI +PRIVATE RgSchCmnRank rgSCHCmnComputeRank +( + RgrTxMode txMode, + U32 *pmiBitMap, + U8 numTxPorts + ) +#else +PRIVATE RgSchCmnRank rgSCHCmnComputeRank(txMode, pmiBitMap, numTxPorts) + RgrTxMode txMode; + U32 *pmiBitMap; + U8 numTxPorts; +#endif +{ + TRC2(rgSCHCmnComputeRank); + + if (numTxPorts ==2 && txMode == RGR_UE_TM_3) + { + RETVALUE (rgSCHCmnComp2TxMode3(pmiBitMap)); + } + else if (numTxPorts ==4 && txMode == RGR_UE_TM_3) + { + RETVALUE (rgSCHCmnComp4TxMode3(pmiBitMap)); + } + else if (numTxPorts ==2 && txMode == RGR_UE_TM_4) + { + RETVALUE (rgSCHCmnComp2TxMode4(pmiBitMap)); + } + else if (numTxPorts ==4 && txMode == RGR_UE_TM_4) + { + RETVALUE (rgSCHCmnComp4TxMode4(pmiBitMap)); + } + else + { + RETVALUE (RG_SCH_CMN_RANK_1); + } +} + +#endif + +/** + * @brief Harq Entity Deinitialization for CMN SCH. + * + * @details + * + * Function : rgSCHCmnDlDeInitHqEnt + * + * Harq Entity Deinitialization for CMN SCH + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlHqEnt *hqE + * @return VOID + **/ +/*KWORK_FIX:Changed function return type to void */ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlDeInitHqEnt +( +RgSchCellCb *cell, +RgSchDlHqEnt *hqE +) +#else +PUBLIC Void rgSCHCmnDlDeInitHqEnt(cell, hqE) +RgSchCellCb *cell; +RgSchDlHqEnt *hqE; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + RgSchDlHqProcCb *hqP; + U8 cnt; + S16 ret; + + TRC2(rgSCHCmnDlDeInitHqEnt); + + ret = cellSchd->apisDl->rgSCHDlUeHqEntDeInit(cell, hqE); + /* Free only If the Harq proc are created*/ + if(RFAILED == ret) + { + } + + for(cnt = 0; cnt < hqE->numHqPrcs; cnt++) + { + hqP = &hqE->procs[cnt]; + if ((RG_SCH_CMN_GET_DL_HQP(hqP))) + { + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&(hqP->sch)), (sizeof(RgSchCmnDlHqProc))); + } + } +#ifdef LTE_ADV + rgSCHLaaDeInitDlHqProcCb (cell, hqE); +#endif + + RETVOID; +} + +/** + * @brief Harq Entity initialization for CMN SCH. + * + * @details + * + * Function : rgSCHCmnDlInitHqEnt + * + * Harq Entity initialization for CMN SCH + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnDlInitHqEnt +( +RgSchCellCb *cell, +RgSchDlHqEnt *hqEnt +) +#else +PUBLIC S16 rgSCHCmnDlInitHqEnt(cell, hqEnt) +RgSchCellCb *cell; +RgSchDlHqEnt *hqEnt; +#endif + +{ + RgSchDlHqProcCb *hqP; + U8 cnt; + + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnDlInitHqEnt); + + for(cnt = 0; cnt < hqEnt->numHqPrcs; cnt++) + { + hqP = &hqEnt->procs[cnt]; + if (rgSCHUtlAllocSBuf(cell->instIdx, + (Data**)&(hqP->sch), (sizeof(RgSchCmnDlHqProc))) != ROK) + { + RETVALUE(RFAILED); + } + } +#ifdef EMTC_ENABLE + if((cell->emtcEnable) &&(hqEnt->ue->isEmtcUe)) + { + if(ROK != cellSchd->apisEmtcDl->rgSCHDlUeHqEntInit(cell, hqEnt)) + { + RETVALUE(RFAILED); + } + + } + else +#endif + { + if(ROK != cellSchd->apisDl->rgSCHDlUeHqEntInit(cell, hqEnt)) + { + RETVALUE(RFAILED); + } + } + + RETVALUE(ROK); +} /* rgSCHCmnDlInitHqEnt */ + +/** + * @brief This function computes distribution of refresh period + * + * @details + * + * Function: rgSCHCmnGetRefreshDist + * Purpose: This function computes distribution of refresh period + * This is required to align set of UEs refresh + * around the different consecutive subframe. + * + * Invoked by: rgSCHCmnGetRefreshPerDist + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnGetRefreshDist +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE U8 rgSCHCmnGetRefreshDist(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + U8 refOffst; +#ifdef DEBUGP + Inst inst = cell->instIdx; +#endif + TRC2(rgSCHCmnGetRefreshDist); + + for(refOffst = 0; refOffst < RGSCH_MAX_REFRESH_OFFSET; refOffst++) + { + if(cell->refreshUeCnt[refOffst] < RGSCH_MAX_REFRESH_GRPSZ) + { + cell->refreshUeCnt[refOffst]++; + ue->refreshOffset = refOffst; + /* printf("UE[%d] refresh offset[%d]. Cell refresh ue count[%d].\n", ue->ueId, refOffst, cell->refreshUeCnt[refOffst]); */ + RETVALUE(refOffst); + } + } + + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "Allocation of refresh distribution failed\n")); + /* We should not enter here normally, but incase of failure, allocating from last offset*/ + cell->refreshUeCnt[refOffst-1]++; + ue->refreshOffset = refOffst-1; + + RETVALUE(refOffst-1); +} +/** + * @brief This function computes initial Refresh Wait Period. + * + * @details + * + * Function: rgSCHCmnGetRefreshPer + * Purpose: This function computes initial Refresh Wait Period. + * This is required to align multiple UEs refresh + * around the same time. + * + * Invoked by: rgSCHCmnGetRefreshPer + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U32 *waitPer + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGetRefreshPer +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 *waitPer +) +#else +PRIVATE Void rgSCHCmnGetRefreshPer(cell, ue, waitPer) +RgSchCellCb *cell; +RgSchUeCb *ue; +U32 *waitPer; +#endif +{ + U32 refreshPer; + U32 crntSubFrm; + + TRC2(rgSCHCmnGetRefreshPer); + + refreshPer = RG_SCH_CMN_REFRESH_TIME * RG_SCH_CMN_REFRESH_TIMERES; + crntSubFrm = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe; + /* Fix: syed align multiple UEs to refresh at same time */ + *waitPer = refreshPer - (crntSubFrm % refreshPer); + *waitPer = RGSCH_CEIL(*waitPer, RG_SCH_CMN_REFRESH_TIMERES); + *waitPer = *waitPer + rgSCHCmnGetRefreshDist(cell, ue); + + RETVOID; +} + + +#ifdef LTE_ADV +/** + * @brief UE initialisation for scheduler. + * + * @details + * + * Function : rgSCHCmnRgrSCellUeCfg + * + * This functions intialises UE specific scheduler + * information for SCELL + * 0. Perform basic validations + * 1. Allocate common sched UE cntrl blk + * 2. Perform DL cfg (allocate Hq Procs Cmn sched cntrl blks) + * 3. Perform UL cfg + * 4. Perform DLFS cfg + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrSCellUeCfg +( +RgSchCellCb *sCell, +RgSchUeCb *ue, +RgrUeSecCellCfg *sCellInfoCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrSCellUeCfg(sCell, ue, sCellInfoCfg, err) +RgSchCellCb *sCell; +RgSchUeCb *ue; +RgrUeSecCellCfg *sCellInfoCfg; +RgSchErrInfo *err; +#endif +{ + U8 i; + S16 ret; + U8 cnt; + RgSchCmnAllocRecord *allRcd; + RgSchDlRbAlloc *allocInfo; + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(ue->cell); + RgSchCmnUlUe *ueUl; + RgSchCmnUlUe *ueUlPcell; + RgSchCmnUe *pCellUeSchCmn; + RgSchCmnUe *ueSchCmn; + RgSchCmnDlUe *ueDl; + RgSchCmnDlUe *pCellUeDl; +#ifdef DEBUGP + Inst inst = ue->cell->instIdx; +#endif + U32 idx = (U8)((sCell->cellId - rgSchCb[sCell->instIdx].genCfg.startCellId)&(CM_LTE_MAX_CELLS-1)); + TRC2(rgSCHCmnRgrSCellUeCfg); + + pCellUeSchCmn = RG_SCH_CMN_GET_UE(ue,ue->cell); + pCellUeDl = &pCellUeSchCmn->dl; + + /* 1. Allocate Common sched control block */ + if((rgSCHUtlAllocSBuf(sCell->instIdx, + (Data**)&(((ue->cellInfo[ue->cellIdToCellIdxMap[idx]])->sch)), (sizeof(RgSchCmnUe))) != ROK)) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "Memory allocation FAILED\n")); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + ueSchCmn = RG_SCH_CMN_GET_UE(ue,sCell); + + /*2. Perform UEs downlink configuration */ + ueDl = &ueSchCmn->dl; + + /*CA TODO*/ + ueDl->mimoInfo = pCellUeDl->mimoInfo; + + if ((ue->mimoInfo.txMode == RGR_UE_TM_4) || + (ue->mimoInfo.txMode == RGR_UE_TM_6)) + { + RG_SCH_CMN_SET_FORCE_TD(ue, sCell, RG_SCH_CMN_TD_NO_PMI); + } + if (ue->mimoInfo.txMode == RGR_UE_TM_3) + { + RG_SCH_CMN_SET_FORCE_TD(ue, sCell, RG_SCH_CMN_TD_RI_1); + } + RGSCH_ARRAY_BOUND_CHECK(sCell->instIdx, rgUeCatTbl, pCellUeSchCmn->cmn.ueCat); + ueDl->maxTbBits = rgUeCatTbl[pCellUeSchCmn->cmn.ueCat].maxDlTbBits; + /*CA dev-Start*/ + U8 ri = 0; + ri = RGSCH_MIN(ri, sCell->numTxAntPorts); + if(((CM_LTE_UE_CAT_6 == pCellUeSchCmn->cmn.ueCat ) + ||(CM_LTE_UE_CAT_7 == pCellUeSchCmn->cmn.ueCat)) + && (4 == ri)) + { + ueDl->maxTbSz = rgUeCatTbl[pCellUeSchCmn->cmn.ueCat].maxDlBits[1]; + } + else + { + ueDl->maxTbSz = rgUeCatTbl[pCellUeSchCmn->cmn.ueCat].maxDlBits[0]; + } + /*CA dev-End*/ + /* Fix : syed Assign hqEnt to UE only if msg4 is done */ +#ifdef LTE_TDD + ueDl->maxSbSz = (rgUeCatTbl[pCellUeSchCmn->cmn.ueCat].maxSftChBits/ + rgSchTddDlNumHarqProcTbl[sCell->ulDlCfgIdx]); +#else + ueDl->maxSbSz = (rgUeCatTbl[pCellUeSchCmn->cmn.ueCat].maxSftChBits/ + RGSCH_NUM_DL_HQ_PROC); +#endif +#ifdef EMTC_ENABLE + rgSCHCmnDlSetUeAllocLmt(sCell, ueDl, ue->isEmtcUe); +#else + rgSCHCmnDlSetUeAllocLmt(sCell, ueDl, FALSE); +#endif + + /* DL ambr */ + /* ambrCfgd config moved to ueCb.dl, as it's not needed for per cell wise*/ + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, sCell); + allocInfo->rnti = ue->ueId; + + /* Initializing the lastCfi value to current cfi value */ + ueDl->lastCfi = cellSchd->dl.currCfi; + + if ((cellSchd->apisDl->rgSCHRgrSCellDlUeCfg(sCell, ue, err)) != ROK) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "Spec Sched DL UE CFG FAILED\n")); + RETVALUE(RFAILED); + } + + /* TODO: enhance for DLFS RB Allocation for SCELLs in future dev */ + + /* DLFS UE Config */ + if (cellSchd->dl.isDlFreqSel) + { + if ((cellSchd->apisDlfs->rgSCHDlfsSCellUeCfg(sCell, ue, sCellInfoCfg, err)) != ROK) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "DLFS UE config FAILED\n")); + RETVALUE(RFAILED); + } + } + + /* TODO: Do UL SCELL CFG during UL CA dev */ + { + ueUl = RG_SCH_CMN_GET_UL_UE(ue, sCell); + + /* TODO_ULCA: SRS for SCELL needs to be handled in the below function call */ + rgSCHCmnUpdUeUlCqiInfo(sCell, ue, ueUl, ueSchCmn, cellSchd, + sCell->isCpUlExtend); + + ret = rgSCHUhmHqEntInit(sCell, ue); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,sCell->cellId,"SCELL UHM HARQ Ent Init " + "Failed for CRNTI:%d", ue->ueId); + RETVALUE(RFAILED); + } + + ueUlPcell = RG_SCH_CMN_GET_UL_UE(ue, ue->cell); + /* Initialize uplink HARQ related information for UE */ + ueUl->hqEnt.maxHqRetx = ueUlPcell->hqEnt.maxHqRetx; + cmLListInit(&ueUl->hqEnt.free); + cmLListInit(&ueUl->hqEnt.inUse); + for(i=0; i < ueUl->hqEnt.numHqPrcs; i++) + { + ueUl->hqEnt.hqProcCb[i].hqEnt = (void*)(&ueUl->hqEnt); + ueUl->hqEnt.hqProcCb[i].procId = i; + ueUl->hqEnt.hqProcCb[i].ulSfIdx = RGSCH_INVALID_INFO; + ueUl->hqEnt.hqProcCb[i].alloc = NULLP; +#ifdef LTEMAC_SPS + /* ccpu00139513- Initializing SPS flags*/ + ueUl->hqEnt.hqProcCb[i].isSpsActvnHqP = FALSE; + ueUl->hqEnt.hqProcCb[i].isSpsOccnHqP = FALSE; +#endif + cmLListAdd2Tail(&ueUl->hqEnt.free, &ueUl->hqEnt.hqProcCb[i].lnk); + ueUl->hqEnt.hqProcCb[i].lnk.node = (PTR)&ueUl->hqEnt.hqProcCb[i]; + } + + /* Allocate UL BSR allocation tracking List */ + cmLListInit(&ueUl->ulAllocLst); + + for (cnt = 0; cnt < RG_SCH_CMN_MAX_ALLOC_TRACK; cnt++) + { + if((rgSCHUtlAllocSBuf(sCell->instIdx, + (Data**)&(allRcd),sizeof(RgSchCmnAllocRecord)) != ROK)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,sCell->cellId,"SCELL Memory allocation FAILED" + "for CRNTI:%d",ue->ueId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + allRcd->allocTime = sCell->crntTime; + cmLListAdd2Tail(&ueUl->ulAllocLst, &allRcd->lnk); + allRcd->lnk.node = (PTR)allRcd; + } + + /* After initialising UL part, do power related init */ + ret = rgSCHPwrUeSCellCfg(sCell, ue, sCellInfoCfg); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,sCell->cellId, "Could not do " + "power config for UE CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + if ((cellSchd->apisEmtcUl->rgSCHRgrUlUeCfg(sCell, ue, NULL, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,sCell->cellId, "Spec Sched UL UE CFG FAILED" + "for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + else +#endif + { + if ((cellSchd->apisUl->rgSCHRgrUlUeCfg(sCell, ue, NULL, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,sCell->cellId, "Spec Sched UL UE CFG FAILED" + "for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + + ue->ul.isUlCaEnabled = TRUE; + } + + RETVALUE(ROK); +} /* rgSCHCmnRgrSCellUeCfg */ + + +/** + * @brief UE initialisation for scheduler. + * + * @details + * + * Function : rgSCHCmnRgrSCellUeDel + * + * This functions Delete UE specific scheduler + * information for SCELL + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrSCellUeDel +( +RgSchUeCellInfo *sCellInfo, +RgSchUeCb *ue +) +#else +PUBLIC S16 rgSCHCmnRgrSCellUeDel(sCellInfo, ue) +RgSchUeCellInfo *sCellInfo; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(ue->cell); + Inst inst = ue->cell->instIdx; + + TRC2(rgSCHCmnRgrSCellUeDel); + + cellSchd->apisDl->rgSCHRgrSCellDlUeDel(sCellInfo, ue); + + /* UL CA */ + rgSCHCmnUlUeDelAllocs(sCellInfo->cell, ue); + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + cellSchd->apisEmtcUl->rgSCHFreeUlUe(sCellInfo->cell, ue); + } + else +#endif + { + cellSchd->apisUl->rgSCHFreeUlUe(sCellInfo->cell, ue); + } + + /* DLFS UE Config */ + if (cellSchd->dl.isDlFreqSel) + { + if ((cellSchd->apisDlfs->rgSCHDlfsSCellUeDel(sCellInfo->cell, ue)) != ROK) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "DLFS Scell del FAILED\n")); + RETVALUE(RFAILED); + } + } + + rgSCHUtlFreeSBuf(sCellInfo->cell->instIdx, + (Data**)(&(sCellInfo->sch)), (sizeof(RgSchCmnUe))); + + + RETVALUE(ROK); +} /* rgSCHCmnRgrSCellUeDel */ + +#endif + +#ifdef RG_5GTF +/** + * @brief Handles 5gtf configuration for a UE + * + * @details + * + * Function : rgSCHCmn5gtfUeCfg + * + * Processing Steps: + * + * - Return ROK + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgrUeCfg *cfg + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmn5gtfUeCfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeCfg *cfg +) +#else +PUBLIC S16 rgSCHCmn5gtfUeCfg(cell, ue, cfg) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeCfg *cfg; +#endif +{ + TRC2(rgSCHCmnRgrUeCfg); + + RgSchUeGrp *ue5gtfGrp; + ue->ue5gtfCb.grpId = cfg->ue5gtfCfg.grpId; + ue->ue5gtfCb.BeamId = cfg->ue5gtfCfg.BeamId; + ue->ue5gtfCb.numCC = cfg->ue5gtfCfg.numCC; + ue->ue5gtfCb.mcs = cfg->ue5gtfCfg.mcs; + ue->ue5gtfCb.maxPrb = cfg->ue5gtfCfg.maxPrb; + + ue->ue5gtfCb.cqiRiPer = 100; + /* 5gtf TODO: CQIs to start from (10,0)*/ + ue->ue5gtfCb.nxtCqiRiOccn.sfn = 10; + ue->ue5gtfCb.nxtCqiRiOccn.subframe = 0; + ue->ue5gtfCb.rank = 1; + + printf("\nschd cfg at mac,%u,%u,%u,%u,%u\n",ue->ue5gtfCb.grpId,ue->ue5gtfCb.BeamId,ue->ue5gtfCb.numCC, + ue->ue5gtfCb.mcs,ue->ue5gtfCb.maxPrb); + + ue5gtfGrp = &(cell->cell5gtfCb.ueGrp5gConf[ue->ue5gtfCb.BeamId]); + + /* TODO_5GTF: Currently handling 1 group only. Need to update when multi group + scheduling comes into picture */ + if(ue5gtfGrp->beamBitMask & (1 << ue->ue5gtfCb.BeamId)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "5GTF_ERROR Invalid beam id CRNTI:%d",cfg->crnti); + RETVALUE(RFAILED); + } + ue5gtfGrp->beamBitMask |= (1 << ue->ue5gtfCb.BeamId); + + RETVALUE(ROK); +} +#endif + +/** + * @brief UE initialisation for scheduler. + * + * @details + * + * Function : rgSCHCmnRgrUeCfg + * + * This functions intialises UE specific scheduler + * information + * 0. Perform basic validations + * 1. Allocate common sched UE cntrl blk + * 2. Perform DL cfg (allocate Hq Procs Cmn sched cntrl blks) + * 3. Perform UL cfg + * 4. Perform DLFS cfg + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[int] RgrUeCfg *ueCfg + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrUeCfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeCfg *ueCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrUeCfg(cell, ue, ueCfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeCfg *ueCfg; +RgSchErrInfo *err; +#endif +{ + RgSchDlRbAlloc *allocInfo; + S16 ret; + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUe *ueSchCmn; + RgSchCmnUlUe *ueUl; + RgSchCmnDlUe *ueDl; + U8 cnt; + RgSchCmnAllocRecord *allRcd; + U32 waitPer; + U32 idx = (U8)((cell->cellId - rgSchCb[cell->instIdx].genCfg.startCellId)&(CM_LTE_MAX_CELLS-1)); + RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ue); + TRC2(rgSCHCmnRgrUeCfg); + + + /* 1. Allocate Common sched control block */ + if((rgSCHUtlAllocSBuf(cell->instIdx, + (Data**)&(((ue->cellInfo[ue->cellIdToCellIdxMap[idx]])->sch)), (sizeof(RgSchCmnUe))) != ROK)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Memory allocation FAILED for CRNTI:%d",ueCfg->crnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + ueSchCmn = RG_SCH_CMN_GET_UE(ue,cell); + ue->dl.ueDlCqiCfg = ueCfg->ueDlCqiCfg; + pCellInfo->acqiCb.aCqiCfg = ueCfg->ueDlCqiCfg.aprdCqiCfg; + if(ueCfg->ueCatEnum > 0 ) + { + /*KWORK_FIX removed NULL chk for ueSchCmn*/ + ueSchCmn->cmn.ueCat = ueCfg->ueCatEnum - 1; + } + else + { + ueSchCmn->cmn.ueCat = 0; /* Assuming enum values correctly set */ + } + cmInitTimers(&ueSchCmn->cmn.tmr, 1); + + /*2. Perform UEs downlink configuration */ + ueDl = &ueSchCmn->dl; + /* RACHO : store the rapId assigned for HandOver UE. + * Append UE to handover list of cmnCell */ + if (ueCfg->dedPreambleId.pres == PRSNT_NODEF) + { + rgSCHCmnDelDedPreamble(cell, ueCfg->dedPreambleId.val); + ueDl->rachInfo.hoRapId = ueCfg->dedPreambleId.val; + cmLListAdd2Tail(&cellSchd->rachCfg.hoUeLst, &ueDl->rachInfo.hoLnk); + ueDl->rachInfo.hoLnk.node = (PTR)ue; + } + + rgSCHCmnUpdUeMimoInfo(ueCfg, ueDl, cell, cellSchd); + + if (ueCfg->txMode.pres == TRUE) + { + if ((ueCfg->txMode.txModeEnum == RGR_UE_TM_4) || + (ueCfg->txMode.txModeEnum == RGR_UE_TM_6)) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_NO_PMI); + } + if (ueCfg->txMode.txModeEnum == RGR_UE_TM_3) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } + } + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgUeCatTbl, ueSchCmn->cmn.ueCat); + ueDl->maxTbBits = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlTbBits; + /*CA dev-Start*/ + U8 ri = 0; + ri = RGSCH_MIN(ri, cell->numTxAntPorts); + if(((CM_LTE_UE_CAT_6 == ueSchCmn->cmn.ueCat ) + ||(CM_LTE_UE_CAT_7 == ueSchCmn->cmn.ueCat)) + && (4 == ri)) + { + ueDl->maxTbSz = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlBits[1]; + } + else + { + ueDl->maxTbSz = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlBits[0]; + } + /*CA dev-End*/ + /* Fix : syed Assign hqEnt to UE only if msg4 is done */ +#ifdef LTE_TDD + ueDl->maxSbSz = (rgUeCatTbl[ueSchCmn->cmn.ueCat].maxSftChBits/ + rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx]); +#else + ueDl->maxSbSz = (rgUeCatTbl[ueSchCmn->cmn.ueCat].maxSftChBits/ + RGSCH_NUM_DL_HQ_PROC); +#endif +#ifdef EMTC_ENABLE + rgSCHCmnDlSetUeAllocLmt(cell, ueDl, ue->isEmtcUe); +#else + rgSCHCmnDlSetUeAllocLmt(cell, ueDl, FALSE); +#endif + /* if none of the DL and UL AMBR are configured then fail the configuration + */ + if((ueCfg->ueQosCfg.dlAmbr == 0) && (ueCfg->ueQosCfg.ueBr == 0)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"UL Ambr and DL Ambr are" + "configured as 0 for CRNTI:%d",ueCfg->crnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + /* DL ambr */ + ue->dl.ambrCfgd = (ueCfg->ueQosCfg.dlAmbr * RG_SCH_CMN_REFRESH_TIME)/100; + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell); + allocInfo->rnti = ue->ueId; + + /* Initializing the lastCfi value to current cfi value */ + ueDl->lastCfi = cellSchd->dl.currCfi; +#ifdef EMTC_ENABLE + if(cell->emtcEnable && ue->isEmtcUe) + { + if ((cellSchd->apisEmtcDl->rgSCHRgrDlUeCfg(cell, ue, ueCfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched DL UE CFG FAILED for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } + + } + else +#endif + { + if ((cellSchd->apisDl->rgSCHRgrDlUeCfg(cell, ue, ueCfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched DL UE CFG FAILED for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } + } + + + + /* 3. Initialize ul part */ + ueUl = &ueSchCmn->ul; + + rgSCHCmnUpdUeUlCqiInfo(cell, ue, ueUl, ueSchCmn, cellSchd, + cell->isCpUlExtend); + + ue->ul.maxBytesPerUePerTti = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxUlBits * \ + RG_SCH_CMN_MAX_BITS_RATIO / (RG_SCH_CMN_UL_COM_DENOM*8); + + ue->ul.cfgdAmbr = (ueCfg->ueQosCfg.ueBr * RG_SCH_CMN_REFRESH_TIME)/100; + ue->ul.effAmbr = ue->ul.cfgdAmbr; + RGSCHCPYTIMEINFO(cell->crntTime, ue->ul.ulTransTime); + + /* Allocate UL BSR allocation tracking List */ + cmLListInit(&ueUl->ulAllocLst); + + for (cnt = 0; cnt < RG_SCH_CMN_MAX_ALLOC_TRACK; cnt++) + { + if((rgSCHUtlAllocSBuf(cell->instIdx, + (Data**)&(allRcd),sizeof(RgSchCmnAllocRecord)) != ROK)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED" + "for CRNTI:%d",ueCfg->crnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + allRcd->allocTime = cell->crntTime; + cmLListAdd2Tail(&ueUl->ulAllocLst, &allRcd->lnk); + allRcd->lnk.node = (PTR)allRcd; + } + /* Allocate common sch cntrl blocks for LCGs */ + for (cnt=0; cntinstIdx, + (Data**)&(ue->ul.lcgArr[cnt].sch), (sizeof(RgSchCmnLcg))); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "SCH struct alloc failed for CRNTI:%d",ueCfg->crnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + } + /* After initialising UL part, do power related init */ + ret = rgSCHPwrUeCfg(cell, ue, ueCfg); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Could not do " + "power config for UE CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } +#ifdef LTEMAC_SPS + ret = rgSCHCmnSpsUeCfg(cell, ue, ueCfg, err); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Could not do " + "SPS config for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } +#endif /* LTEMAC_SPS */ + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + if ((cellSchd->apisEmtcUl->rgSCHRgrUlUeCfg(cell, ue, ueCfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Spec Sched UL UE CFG FAILED" + "for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } + } + else +#endif + { + if ((cellSchd->apisUl->rgSCHRgrUlUeCfg(cell, ue, ueCfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Spec Sched UL UE CFG FAILED" + "for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } + } + + /* DLFS UE Config */ + if (cellSchd->dl.isDlFreqSel) + { + if ((cellSchd->apisDlfs->rgSCHDlfsUeCfg(cell, ue, ueCfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "DLFS UE config FAILED" + "for CRNTI:%d",ueCfg->crnti); + RETVALUE(RFAILED); + } + } + + /* Fix: syed align multiple UEs to refresh at same time */ + rgSCHCmnGetRefreshPer(cell, ue, &waitPer); + /* Start UE Qos Refresh Timer */ + rgSCHCmnAddUeToRefreshQ(cell, ue, waitPer); +#ifdef RG_5GTF + rgSCHCmn5gtfUeCfg(cell, ue, ueCfg); +#endif + + RETVALUE(ROK); +} /* rgSCHCmnRgrUeCfg */ + +/** + * @brief UE TX mode reconfiguration handler. + * + * @details + * + * Function : rgSCHCmnDlHdlTxModeRecfg + * + * This functions updates UE specific scheduler + * information upon UE reconfiguration. + * + * @param[in] RgSchUeCb *ue + * @param[in] RgrUeRecfg *ueRecfg + * @return Void + **/ +#ifdef TFU_UPGRADE +#ifdef ANSI +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeRecfg *ueRecfg, +U8 numTxPorts +) +#else +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg(cell, ue, ueRecfg, numTxPorts) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeRecfg *ueRecfg; +U8 numTxPorts; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeRecfg *ueRecfg +) +#else +PRIVATE Void rgSCHCmnDlHdlTxModeRecfg(cell, ue, ueRecfg) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeRecfg *ueRecfg; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlHdlTxModeRecfg); + + if (ueRecfg->txMode.pres != PRSNT_NODEF) + { + RETVOID; + } + /* ccpu00140894- Starting Timer for TxMode Transition Completion*/ + ue->txModeTransCmplt =FALSE; + rgSCHTmrStartTmr (ue->cell, ue, RG_SCH_TMR_TXMODE_TRNSTN, RG_SCH_TXMODE_TRANS_TIMER); + if (ueRecfg->txMode.tmTrnstnState == RGR_TXMODE_RECFG_CMPLT) + { + RG_SCH_CMN_UNSET_FORCE_TD(ue, cell, + RG_SCH_CMN_TD_TXMODE_RECFG); + /* MS_WORKAROUND for ccpu00123186 MIMO Fix Start: need to set FORCE TD bitmap based on TX mode */ + ueDl->mimoInfo.ri = 1; + if ((ueRecfg->txMode.txModeEnum == RGR_UE_TM_4) || + (ueRecfg->txMode.txModeEnum == RGR_UE_TM_6)) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_NO_PMI); + } + if (ueRecfg->txMode.txModeEnum == RGR_UE_TM_3) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } + /* MIMO Fix End: need to set FORCE TD bitmap based on TX mode */ + RETVOID; + } + if (ueRecfg->txMode.tmTrnstnState == RGR_TXMODE_RECFG_START) + { + /* start afresh forceTD masking */ + RG_SCH_CMN_INIT_FORCE_TD(ue, cell, 0); + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_TXMODE_RECFG); + /* Intialize MIMO related parameters of UE */ + +#ifdef TFU_UPGRADE + if(ueRecfg->txMode.pres) + { + if((ueRecfg->txMode.txModeEnum ==RGR_UE_TM_3) || + (ueRecfg->txMode.txModeEnum ==RGR_UE_TM_4)) + { + if(ueRecfg->ueCodeBookRstRecfg.pres) + { + ueDl->mimoInfo.ri = + rgSCHCmnComputeRank(ueRecfg->txMode.txModeEnum, + ueRecfg->ueCodeBookRstRecfg.pmiBitMap, numTxPorts); + } + else + { + ueDl->mimoInfo.ri = 1; + } + } + else + { + ueDl->mimoInfo.ri = 1; + } + } + else + { + ueDl->mimoInfo.ri = 1; + } +#else + ueDl->mimoInfo.ri = 1; +#endif /* TFU_UPGRADE */ + if ((ueRecfg->txMode.txModeEnum == RGR_UE_TM_4) || + (ueRecfg->txMode.txModeEnum == RGR_UE_TM_6)) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_NO_PMI); + } + if (ueRecfg->txMode.txModeEnum == RGR_UE_TM_3) + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } + RETVOID; + } +} +/*********************************************************** + * + * Func : rgSCHCmnUpdUeMimoInfo + * + * Desc : Updates UL and DL Ue Information + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdUeMimoInfo +( +RgrUeCfg *ueCfg, +RgSchCmnDlUe *ueDl, +RgSchCellCb *cell, +RgSchCmnCell *cellSchd +) +#else +PRIVATE Void rgSCHCmnUpdUeMimoInfo(ueCfg, ueDl, cell, cellSchd) +RgrUeCfg *ueCfg; +RgSchCmnDlUe *ueDl; +RgSchCellCb *cell; +RgSchCmnCell *cellSchd; +#endif +{ + TRC2(rgSCHCmnUpdUeMimoInfo) +#ifdef TFU_UPGRADE + if(ueCfg->txMode.pres) + { + if((ueCfg->txMode.txModeEnum ==RGR_UE_TM_3) || + (ueCfg->txMode.txModeEnum ==RGR_UE_TM_4)) + { + if(ueCfg->ueCodeBookRstCfg.pres) + { + ueDl->mimoInfo.ri = + rgSCHCmnComputeRank(ueCfg->txMode.txModeEnum, + ueCfg->ueCodeBookRstCfg.pmiBitMap, cell->numTxAntPorts); + } + else + { + ueDl->mimoInfo.ri = 1; + } + } + else + { + ueDl->mimoInfo.ri = 1; + } + } + else + { + ueDl->mimoInfo.ri = 1; + } + +#else + ueDl->mimoInfo.ri = 1; +#endif /*TFU_UPGRADE */ + ueDl->mimoInfo.cwInfo[0].cqi = cellSchd->dl.ccchCqi; + ueDl->mimoInfo.cwInfo[1].cqi = cellSchd->dl.ccchCqi; + + RETVOID; +} +/*********************************************************** + * + * Func : rgSCHCmnUpdUeUlCqiInfo + * + * Desc : Updates UL and DL Ue Information + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdUeUlCqiInfo +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchCmnUlUe *ueUl, +RgSchCmnUe *ueSchCmn, +RgSchCmnCell *cellSchd, +Bool isEcp +) +#else +PRIVATE Void rgSCHCmnUpdUeUlCqiInfo(cell, ue, ueUl, ueSchCmn, cellSchd, isEcp) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchCmnUlUe *ueUl; +RgSchCmnUe *ueSchCmn; +RgSchCmnCell *cellSchd; +Bool isEcp; +#endif +{ + + TRC2(rgSCHCmnUpdUeUlCqiInfo) + +#ifdef TFU_UPGRADE + if(ue->srsCb.srsCfg.type == RGR_SCH_SRS_SETUP) + { + if(ue->ul.ulTxAntSel.pres) + { + ueUl->crntUlCqi[ue->srsCb.selectedAnt] = cellSchd->ul.dfltUlCqi; + ueUl->validUlCqi = ueUl->crntUlCqi[ue->srsCb.selectedAnt]; + } + else + { + ueUl->crntUlCqi[0] = cellSchd->ul.dfltUlCqi; + ueUl->validUlCqi = ueUl->crntUlCqi[0]; + } + ue->validTxAnt = ue->srsCb.selectedAnt; + } + else + { + ueUl->validUlCqi = cellSchd->ul.dfltUlCqi; + ue->validTxAnt = 0; + } +#ifdef UL_LA + ueUl->ulLaCb.cqiBasediTbs = rgSchCmnUlCqiToTbsTbl[isEcp] + [ueUl->validUlCqi] * 100; + ueUl->ulLaCb.deltaiTbs = 0; +#endif + +#else + ueUl->crntUlCqi[0] = cellSchd->ul.dfltUlCqi; +#endif /*TFU_UPGRADE */ + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgUeCatTbl, ueSchCmn->cmn.ueCat); + if (rgUeCatTbl[ueSchCmn->cmn.ueCat].ul64qamSup == FALSE) + { + ueUl->maxUlCqi = cellSchd->ul.max16qamCqi; + } + else + { + ueUl->maxUlCqi = RG_SCH_CMN_UL_NUM_CQI - 1; + } + + RETVOID; +} +/*********************************************************** + * + * Func : rgSCHCmnUpdUeCatCfg + * + * Desc : Updates UL and DL Ue Information + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdUeCatCfg +( +RgSchUeCb *ue, +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnUpdUeCatCfg(ue, cell) +RgSchUeCb *ue; +RgSchCellCb *cell; +#endif +{ + RgSchDlHqEnt *hqE = NULLP; + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue,cell); + RgSchCmnCell *cellSchd = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnUpdUeCatCfg) + + ueDl->maxTbBits = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlTbBits; + + hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell); + /*CA dev-Start*/ + U8 ri = 0; + ri = RGSCH_MIN(ri, cell->numTxAntPorts); + if(((CM_LTE_UE_CAT_6 == ueSchCmn->cmn.ueCat ) + ||(CM_LTE_UE_CAT_7 == ueSchCmn->cmn.ueCat)) + && (RG_SCH_MAX_TX_LYRS_4 == ri)) + { + ueDl->maxTbSz = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlBits[1]; + } + else + { + ueDl->maxTbSz = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxDlBits[0]; + } + /*CA dev-End*/ + ueDl->maxSbSz = (rgUeCatTbl[ueSchCmn->cmn.ueCat].maxSftChBits/ + hqE->numHqPrcs); + if (rgUeCatTbl[ueSchCmn->cmn.ueCat].ul64qamSup == FALSE) + { + ueUl->maxUlCqi = cellSchd->ul.max16qamCqi; + } + else + { + ueUl->maxUlCqi = RG_SCH_CMN_UL_NUM_CQI - 1; + } + ue->ul.maxBytesPerUePerTti = rgUeCatTbl[ueSchCmn->cmn.ueCat].maxUlBits * \ + RG_SCH_CMN_MAX_BITS_RATIO / (RG_SCH_CMN_UL_COM_DENOM*8); + RETVOID; +} + +/** + * @brief UE reconfiguration for scheduler. + * + * @details + * + * Function : rgSChCmnRgrUeRecfg + * + * This functions updates UE specific scheduler + * information upon UE reconfiguration. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[int] RgrUeRecfg *ueRecfg + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrUeRecfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeRecfg *ueRecfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrUeRecfg(cell, ue, ueRecfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeRecfg *ueRecfg; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSchCmn = RG_SCH_CMN_GET_CELL(cell); + U32 waitPer; + + TRC2(rgSCHCmnRgrUeRecfg); + /* Basic validations */ + if (ueRecfg->ueRecfgTypes & RGR_UE_TXMODE_RECFG) + { +#ifdef TFU_UPGRADE + rgSCHCmnDlHdlTxModeRecfg(cell, ue, ueRecfg, cell->numTxAntPorts); +#else + rgSCHCmnDlHdlTxModeRecfg(cell, ue, ueRecfg); +#endif /* TFU_UPGRADE */ + } + if(ueRecfg->ueRecfgTypes & RGR_UE_CSG_PARAM_RECFG) + { + ue->csgMmbrSta = ueRecfg->csgMmbrSta; + } + /* Changes for UE Category reconfiguration feature */ + if(ueRecfg->ueRecfgTypes & RGR_UE_UECAT_RECFG) + { + rgSCHCmnUpdUeCatCfg(ue, cell); + } + if (ueRecfg->ueRecfgTypes & RGR_UE_APRD_DLCQI_RECFG) + { + RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ue); + pCellInfo->acqiCb.aCqiCfg = ueRecfg->aprdDlCqiRecfg; + } +#ifndef TFU_UPGRADE + if (ueRecfg->ueRecfgTypes & RGR_UE_PRD_DLCQI_RECFG) + { + if ((ueRecfg->prdDlCqiRecfg.pres == TRUE) + && (ueRecfg->prdDlCqiRecfg.prdModeEnum != RGR_PRD_CQI_MOD10) + && (ueRecfg->prdDlCqiRecfg.prdModeEnum != RGR_PRD_CQI_MOD20)) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Unsupported periodic CQI " + "reporting mode %d for old CRNIT:%d", + (int)ueRecfg->prdDlCqiRecfg.prdModeEnum,ueRecfg->oldCrnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + ue->dl.ueDlCqiCfg.prdCqiCfg = ueRecfg->prdDlCqiRecfg; + } +#endif + + if (ueRecfg->ueRecfgTypes & RGR_UE_ULPWR_RECFG) + { + if (rgSCHPwrUeRecfg(cell, ue, ueRecfg) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Power Reconfiguration Failed for OLD CRNTI:%d",ueRecfg->oldCrnti); + RETVALUE(RFAILED); + } + } + + if (ueRecfg->ueRecfgTypes & RGR_UE_QOS_RECFG) + { + /* Uplink Sched related Initialization */ + if ((ueRecfg->ueQosRecfg.dlAmbr == 0) && (ueRecfg->ueQosRecfg.ueBr == 0)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Ul Ambr and DL Ambr " + "configured as 0 for OLD CRNTI:%d",ueRecfg->oldCrnti); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + ue->ul.cfgdAmbr = (ueRecfg->ueQosRecfg.ueBr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + /* Downlink Sched related Initialization */ + ue->dl.ambrCfgd = (ueRecfg->ueQosRecfg.dlAmbr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + /* Fix: syed Update the effAmbr and effUeBR fields w.r.t the + * new QOS configuration */ + rgSCHCmnDelUeFrmRefreshQ(cell, ue); + /* Fix: syed align multiple UEs to refresh at same time */ + rgSCHCmnGetRefreshPer(cell, ue, &waitPer); + rgSCHCmnApplyUeRefresh(cell, ue); + rgSCHCmnAddUeToRefreshQ(cell, ue, waitPer); + } +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + if ((cellSchCmn->apisEmtcUl->rgSCHRgrUlUeRecfg(cell, ue, ueRecfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched UL UE ReCFG FAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + if ((cellSchCmn->apisEmtcDl->rgSCHRgrDlUeRecfg(cell, ue, ueRecfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched DL UE ReCFG FAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + else +#endif + { + if ((cellSchCmn->apisUl->rgSCHRgrUlUeRecfg(cell, ue, ueRecfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched UL UE ReCFG FAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + if ((cellSchCmn->apisDl->rgSCHRgrDlUeRecfg(cell, ue, ueRecfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "Spec Sched DL UE ReCFG FAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + /* DLFS UE Config */ + if (cellSchCmn->dl.isDlFreqSel) + { + if ((cellSchCmn->apisDlfs->rgSCHDlfsUeRecfg(cell, ue, \ + ueRecfg, err)) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "DLFS UE re-config FAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + +#ifdef LTEMAC_SPS + /* Invoke re-configuration on SPS module */ + if (rgSCHCmnSpsUeRecfg(cell, ue, ueRecfg, err) != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "DL SPS ReCFG FAILED for UE CRNTI:%d", ue->ueId); + RETVALUE(RFAILED); + } +#endif + + RETVALUE(ROK); +} /* rgSCHCmnRgrUeRecfg*/ + +/*********************************************************** + * + * Func : rgSCHCmnUlUeDelAllocs + * + * Desc : Deletion of all UE allocations. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlUeDelAllocs +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnUlUeDelAllocs(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell); + U8 i; +#ifdef LTEMAC_SPS + RgSchCmnUlUeSpsInfo *ulSpsUe = RG_SCH_CMN_GET_UL_SPS_UE(ue,cell); +#endif + TRC2(rgSCHCmnUlUeDelAllocs); + + for (i = 0; i < ueUl->hqEnt.numHqPrcs; ++i) + { + RgSchUlHqProcCb *proc = rgSCHUhmGetUlHqProc(cell, ue, i); + +#ifdef ERRCLS_KW + /* proc can't be NULL here */ + if (proc) +#endif + { + /* R8 Upgrade */ + proc->ndi = 0; + if (proc->alloc) + { + /* Added Insure Fixes Of reading Dangling memory.NULLed crntAlloc */ +#ifdef LTEMAC_SPS + if(proc->alloc == ulSpsUe->ulSpsSchdInfo.crntAlloc) + { + ulSpsUe->ulSpsSchdInfo.crntAlloc = NULLP; + ulSpsUe->ulSpsSchdInfo.crntAllocSf = NULLP; + } +#endif +#ifdef EMTC_ENABLE + rgSCHCmnUlFreeAllocation(cell, &cellUl->ulSfArr[proc->ulSfIdx], + proc->alloc,ue->isEmtcUe); +#else + rgSCHCmnUlFreeAllocation(cell, &cellUl->ulSfArr[proc->ulSfIdx], + proc->alloc); +#endif + /* PHY probably needn't be intimated since + * whatever intimation it needs happens at the last minute + */ + } + /* Fix: syed Adaptive Msg3 Retx crash. Remove the harqProc + * from adaptive retx List. */ + if (proc->reTxLnk.node) + { + { + //TODO_SID: Need to take care + cmLListDelFrm(&cellUl->reTxLst, &proc->reTxLnk); + proc->reTxLnk.node = (PTR)NULLP; + } + } + } + } + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnDelUeFrmRefreshQ + * + * Desc : Adds a UE to refresh queue, so that the UE is + * periodically triggered to refresh it's GBR and + * AMBR values. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDelUeFrmRefreshQ +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnDelUeFrmRefreshQ(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *sched = RG_SCH_CMN_GET_CELL(cell); + CmTmrArg arg; + RgSchCmnUeInfo *ueSchd = RG_SCH_CMN_GET_CMN_UE(ue); + + TRC2(rgSCHCmnDelUeFrmRefreshQ); + +#ifdef RGL_SPECIFIC_CHANGES + if(ue->refreshOffset < RGSCH_MAX_REFRESH_GRPSZ) + { + if(cell->refreshUeCnt[ue->refreshOffset]) + { + cell->refreshUeCnt[ue->refreshOffset]--; + } + } +#endif + + + cmMemset((U8 *)&arg, 0, sizeof(arg)); + arg.tqCp = &sched->tmrTqCp; + arg.tq = sched->tmrTq; + arg.timers = &ueSchd->tmr; + arg.cb = (PTR)ue; + arg.tNum = 0; + arg.max = 1; + arg.evnt = RG_SCH_CMN_EVNT_UE_REFRESH; + + cmRmvCbTq(&arg); + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnUeCcchSduDel + * + * Desc : Clear CCCH SDU scheduling context. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUeCcchSduDel +( +RgSchCellCb *cell, +RgSchUeCb *ueCb +) +#else +PRIVATE Void rgSCHCmnUeCcchSduDel(cell, ueCb) +RgSchCellCb *cell; +RgSchUeCb *ueCb; +#endif +{ + RgSchDlHqEnt *hqE = NULLP; + RgSchDlHqProcCb *ccchSduHqP = NULLP; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnUeCcchSduDel); + + hqE = RG_SCH_CMN_GET_UE_HQE(ueCb, cell); + if (hqE == NULLP) + { + RETVOID; + } + ccchSduHqP = hqE->ccchSduProc; + if(ueCb->ccchSduLnk.node != NULLP) + { + /* Remove the ccchSduProc if it is in the Tx list */ + cmLListDelFrm(&(cell->ccchSduUeLst), &(ueCb->ccchSduLnk)); + ueCb->ccchSduLnk.node = NULLP; + } + else if(ccchSduHqP != NULLP) + { + /* Fix for crash due to stale pdcch. Release ccch pdcch*/ + if(ccchSduHqP->pdcch) + { + cmLListDelFrm(&ccchSduHqP->subFrm->pdcchInfo.pdcchs, + &ccchSduHqP->pdcch->lnk); + cmLListAdd2Tail(&cell->pdcchLst, &ccchSduHqP->pdcch->lnk); + ccchSduHqP->pdcch = NULLP; + } + if(ccchSduHqP->tbInfo[0].ccchSchdInfo.retxLnk.node != NULLP) + { + /* Remove the ccchSduProc if it is in the retx list */ + cmLListDelFrm(&cellSch->dl.ccchSduRetxLst, + &ccchSduHqP->tbInfo[0].ccchSchdInfo.retxLnk); + /* ccchSduHqP->tbInfo[0].ccchSchdInfo.retxLnk.node = NULLP; */ + rgSCHDhmRlsHqpTb(ccchSduHqP, 0, TRUE); + } + else if ((ccchSduHqP->subFrm != NULLP) && + (ccchSduHqP->hqPSfLnk.node != NULLP)) + { + rgSCHUtlDlHqPTbRmvFrmTx(ccchSduHqP->subFrm, + ccchSduHqP, 0, FALSE); + rgSCHDhmRlsHqpTb(ccchSduHqP, 0, TRUE); + } + } + RETVOID; +} + + + + +/** + * @brief UE deletion for scheduler. + * + * @details + * + * Function : rgSCHCmnUeDel + * + * This functions deletes all scheduler information + * pertaining to an UE. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUeDel +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUeDel(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchDlHqEnt *hqE = NULLP; + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + CmLList *node; + RgSchCmnAllocRecord *allRcd; + U8 cnt; + RgSchCmnCell *cellSchCmn = RG_SCH_CMN_GET_CELL(cell); + U32 idx = 0; + TRC2(rgSCHCmnUeDel); + + if (RG_SCH_CMN_GET_UE(ue,cell) == NULLP) + { + /* Common scheduler config has not happened yet */ + RETVOID; + } + hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell); + if(hqE) + { + /* UE Free can be triggered before MSG4 done when dlHqE is not updated */ +#ifdef EMTC_ENABLE + if(ue->isEmtcUe) + { + rgSCHEmtcCmnUeCcchSduDel(cell, ue); + } + else +#endif + { + rgSCHCmnUeCcchSduDel(cell, ue); + } + } + rgSCHCmnDelUeFrmRefreshQ(cell, ue); + + rgSCHCmnUlUeDelAllocs(cell, ue); + + rgSCHCmnDelRachInfo(cell, ue); + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + cellSchCmn->apisEmtcUl->rgSCHFreeUlUe(cell, ue); + } + else +#endif + { + cellSchCmn->apisUl->rgSCHFreeUlUe(cell, ue); + } +#ifdef LTE_ADV + if (ue->numSCells) + { + for(idx = 1; idx <= RG_SCH_MAX_SCELL ; idx++) + { + if(ue->cellInfo[idx] != NULLP) + { + rgSCHSCellDelUeSCell(cell,ue,idx); + } + } + + } +#endif +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + cellSchCmn->apisEmtcDl->rgSCHFreeDlUe(cell, ue); + } + else +#endif + { + cellSchCmn->apisDl->rgSCHFreeDlUe(cell, ue); + } + rgSCHPwrUeDel(cell, ue); + +#ifdef LTEMAC_SPS + rgSCHCmnSpsUeDel(cell, ue); +#endif /* LTEMAC_SPS*/ + + /* CA Dev Start*/ + rgSchCmnDlSfHqDel(ue, cell); + /* CA Dev End*/ + /* DLFS UE delete */ + if (cellSchCmn->dl.isDlFreqSel) + { + cellSchCmn->apisDlfs->rgSCHDlfsUeDel(cell, ue); + } + node = ueUl->ulAllocLst.first; + +/* ccpu00117052 - MOD - Passing double pointer in all the places of + rgSCHUtlFreeSBuf function call for proper NULLP assignment*/ + while(node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + node = node->next; + cmLListDelFrm(&ueUl->ulAllocLst, &allRcd->lnk); + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&allRcd), (sizeof(RgSchCmnAllocRecord))); + } + + for(cnt = 0; cnt < RGSCH_MAX_LCG_PER_UE; cnt++) + { + if (ue->ul.lcgArr[cnt].sch != NULLP) + { + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&(ue->ul.lcgArr[cnt].sch)), (sizeof(RgSchCmnLcg))); + } + } + + /* Fix : syed Moved hqEnt deinit to rgSCHCmnDlDeInitHqEnt */ + idx = (U8)((cell->cellId - rgSchCb[cell->instIdx].genCfg.startCellId) & (CM_LTE_MAX_CELLS - 1)); + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&(((ue->cellInfo[ue->cellIdToCellIdxMap[idx]])->sch))), (sizeof(RgSchCmnUe))); + RETVOID; +} /* rgSCHCmnUeDel */ + + +/** + * @brief This function handles the common code rate configurations + * done as part of RgrCellCfg/RgrCellRecfg. + * + * @details + * + * Function: rgSCHCmnDlCnsdrCmnRt + * Purpose: This function handles the common code rate configurations + * done as part of RgrCellCfg/RgrCellRecfg. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgrDlCmnCodeRateCfg *dlCmnCodeRate + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlCnsdrCmnRt +( +RgSchCellCb *cell, +RgrDlCmnCodeRateCfg *dlCmnCodeRate +) +#else +PRIVATE S16 rgSCHCmnDlCnsdrCmnRt(cell, dlCmnCodeRate) +RgSchCellCb *cell; +RgrDlCmnCodeRateCfg *dlCmnCodeRate; +#endif +{ + RgSchCmnCell *cellDl = RG_SCH_CMN_GET_CELL(cell); + U32 bitsPerRb; + U32 bitsPer2Rb; + U32 bitsPer3Rb; + U8 i, rbNum; + U32 pdcchBits; + + TRC2(rgSCHCmnDlCnsdrCmnRt); + + /* code rate is bits per 1024 phy bits, since modl'n scheme is 2. it is + * bits per 1024/2 REs */ + if (dlCmnCodeRate->bcchPchRaCodeRate != 0) + { + bitsPerRb = ((dlCmnCodeRate->bcchPchRaCodeRate * 2) * + cellDl->dl.noResPerRb[3])/1024; + } + else + { + bitsPerRb = ((RG_SCH_CMN_DEF_BCCHPCCH_CODERATE * 2) * + cellDl->dl.noResPerRb[3])/1024; + } + /* Store bitsPerRb in cellDl->dl to use later to determine + * Number of RBs for UEs with SI-RNTI, P-RNTI and RA-RNTI */ + cellDl->dl.bitsPerRb = bitsPerRb; + /* ccpu00115595 end*/ + /* calculate the ITbs for 2 RBs. Initialize ITbs to MAX value */ + i = 0; + rbNum = 2; + bitsPer2Rb = bitsPerRb * rbNum; + while ((i < 9) && (rgTbSzTbl[0][i][rbNum - 1] <= bitsPer2Rb)) + i++; + + (i <= 1)? (cellDl->dl.cmnChITbs.iTbs2Rbs = 0) : + (cellDl->dl.cmnChITbs.iTbs2Rbs = i-1); + + /* calculate the ITbs for 3 RBs. Initialize ITbs to MAX value */ + i = 0; + rbNum = 3; + bitsPer3Rb = bitsPerRb * rbNum; + while ((i < 9) && (rgTbSzTbl[0][i][rbNum - 1] <= bitsPer3Rb)) + i++; + + (i <= 1)? (cellDl->dl.cmnChITbs.iTbs3Rbs = 0) : + (cellDl->dl.cmnChITbs.iTbs3Rbs = i-1); + + + pdcchBits = 1 + /* Flag for format0/format1a differentiation */ + 1 + /* Localized/distributed VRB assignment flag */ + 5 + /* For mcs */ +#ifndef LTE_TDD + 3 + /* Harq process Id */ +#else + 4 + /* Harq process Id */ + 2 + /* UL Index or DAI */ +#endif + 1 + /* New Data Indicator */ + 2 + /* For RV */ + 2 + /* For tpc */ + 1 + rgSCHUtlLog32bitNbase2((cell->bwCfg.dlTotalBw * \ + (cell->bwCfg.dlTotalBw + 1))/2); + /* Resource block assignment ceil[log2(bw(bw+1)/2)] : \ + Since VRB is local */ + /* For TDD consider DAI */ + + /* Convert the pdcchBits to actual pdcchBits required for transmission */ + if (dlCmnCodeRate->pdcchCodeRate != 0) + { + pdcchBits = (pdcchBits * 1024)/dlCmnCodeRate->pdcchCodeRate; + if (pdcchBits <= 288) /* 288 : Num of pdcch bits for aggrLvl=4 */ + { + cellDl->dl.cmnChAggrLvl = CM_LTE_AGGR_LVL4; + } + else /* 576 : Num of pdcch bits for aggrLvl=8 */ + { + cellDl->dl.cmnChAggrLvl = CM_LTE_AGGR_LVL8; + } + } + else + { + cellDl->dl.cmnChAggrLvl = CM_LTE_AGGR_LVL4; + } + if (dlCmnCodeRate->ccchCqi == 0) + { + RETVALUE(RFAILED); + } + else + { + cellDl->dl.ccchCqi = dlCmnCodeRate->ccchCqi; + } + RETVALUE(ROK); +} + +#ifdef LTE_TDD +/** + * @brief This function handles the configuration of cell for the first + * time by the scheduler. + * + * @details + * + * Function: rgSCHCmnDlRgrCellCfg + * Purpose: Configuration received is stored into the data structures + * Also, update the scheduler with the number of frames of + * RACH preamble transmission. + * + * Invoked by: BO and Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgrCellCfg* cfg + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlRgrCellCfg +( +RgSchCellCb *cell, +RgrCellCfg *cfg, +RgSchErrInfo *err +) +#else +PRIVATE S16 rgSCHCmnDlRgrCellCfg(cell, cfg, err) +RgSchCellCb *cell; +RgrCellCfg *cfg; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSch; + U8 cp; + U8 sfCount; + U8 numPdcchSym; + U8 noSymPerSlot; + U8 maxDlSubfrms = cell->numDlSubfrms; + U8 splSubfrmIdx = cfg->spclSfCfgIdx; + U8 swPtCnt = 0; + Bool isSplfrm; + RgSchTddSubfrmInfo subfrmInfo = rgSchTddMaxUlSubfrmTbl[cell->ulDlCfgIdx]; + S16 ret; + U8 splSfIdx; + U8 antPortIdx; + U8 numCrs; + U8 cfi; + U8 cfiIdx; + RgSchDlSf *sf; + U8 splSfCfi; + U8 mPhich; + + TRC2(rgSCHCmnDlRgrCellCfg); + + + cellSch = RG_SCH_CMN_GET_CELL(cell); + cellSch->dl.numRaSubFrms = rgRaPrmblToRaFrmTbl[cell->\ + rachCfg.preambleFormat]; + /*[ccpu00138532]-ADD-fill the Msg4 Harq data */ + cell->dlHqCfg.maxMsg4HqTx = cfg->dlHqCfg.maxMsg4HqTx; + + /* Msg4 Tx Delay = (HARQ_RTT * MAX_MSG4_HARQ_RETX) + + 3 TTI (MAX L1+L2 processing delay at the UE) */ + cellSch->dl.msg4TxDelay = (cfg->dlHqCfg.maxMsg4HqTx-1) * + rgSchCmnHarqRtt[cell->ulDlCfgIdx] + 3; + cellSch->dl.maxUePerDlSf = cfg->maxUePerDlSf; + cellSch->dl.maxUeNewTxPerTti = cfg->maxDlUeNewTxPerTti; + if (cfg->maxUePerDlSf == 0) + { + cellSch->dl.maxUePerDlSf = RG_SCH_CMN_MAX_UE_PER_DL_SF; + } + if (cellSch->dl.maxUePerDlSf < cellSch->dl.maxUeNewTxPerTti) + { + RETVALUE(RFAILED); + } + + + if (cell->bwCfg.dlTotalBw <= 10) + { + cfiIdx = 1; + numPdcchSym = 2; + } + else + { + cfiIdx = 0; + numPdcchSym = 1; + } + /* DwPTS Scheduling Changes Start */ + cellSch->dl.splSfCfg = splSubfrmIdx; + + if (cfg->isCpDlExtend == TRUE) + { + if((0 == splSubfrmIdx) || (4 == splSubfrmIdx) || + (7 == splSubfrmIdx) || (8 == splSubfrmIdx) + ) + { + cell->splSubfrmCfg.isDlDataAllowed = FALSE; + } + else + { + cell->splSubfrmCfg.isDlDataAllowed = TRUE; + } + } + else + { + /* Refer to 36.213 Section 7.1.7 */ + if((0 == splSubfrmIdx) || (5 == splSubfrmIdx)) + { + cell->splSubfrmCfg.isDlDataAllowed = FALSE; + } + else + { + cell->splSubfrmCfg.isDlDataAllowed = TRUE; + } + } + /* DwPTS Scheduling Changes End */ + + splSfCfi = RGSCH_MIN(cell->dynCfiCb.maxCfi, cellSch->cfiCfg.cfi); + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, splSfCfi); + + for (sfCount = 0; sfCount < maxDlSubfrms; sfCount++) + { + sf = cell->subFrms[sfCount]; + /* Sfcount matches the first special subframe occurs at Index 0 + * or subsequent special subframes */ + if(subfrmInfo.switchPoints == 1) + { + isSplfrm = rgSCHCmnIsSplSubfrm(swPtCnt, sfCount, + RG_SCH_CMN_10_MS_PRD, &subfrmInfo); + } + else + { + isSplfrm = rgSCHCmnIsSplSubfrm(swPtCnt, sfCount, + RG_SCH_CMN_5_MS_PRD, &subfrmInfo); + } + if(isSplfrm == TRUE) + { + swPtCnt++; + /* DwPTS Scheduling Changes Start */ + if (cell->splSubfrmCfg.isDlDataAllowed == TRUE) + { + sf->sfType = RG_SCH_SPL_SF_DATA; + } + else + { + sf->sfType = RG_SCH_SPL_SF_NO_DATA; + } + /* DwPTS Scheduling Changes End */ + } + else + { + /* DwPTS Scheduling Changes Start */ + if (sf->sfNum != 0) + { + sf->sfType = RG_SCH_DL_SF; + } + else + { + sf->sfType = RG_SCH_DL_SF_0; + } + /* DwPTS Scheduling Changes End */ + } + + /* Calculate the number of CCEs per subframe in the cell */ + mPhich = rgSchTddPhichMValTbl[cell->ulDlCfgIdx][sf->sfNum]; + if(cell->dynCfiCb.isDynCfiEnb == TRUE) + { + /* In case if Dynamic CFI feature is enabled, default CFI + * value 1 is used */ + sf->nCce = cell->dynCfiCb.cfi2NCceTbl[mPhich][1]; + } + else + { + if (sf->sfType == RG_SCH_SPL_SF_DATA) + { + sf->nCce = cell->dynCfiCb.cfi2NCceTbl[mPhich][splSfCfi]; + } + else + { + sf->nCce = cell->dynCfiCb.cfi2NCceTbl[mPhich][RGSCH_MIN(cell->dynCfiCb.maxCfi, cellSch->cfiCfg.cfi)]; + } + } + } + + /* Intialize the RACH response scheduling related infromation */ + if(rgSCHCmnDlRachInfoInit(cell) != ROK) + { + RETVALUE(RFAILED); + } + + /* Allocate PRACH preamble list */ + rgSCHCmnDlCreateRachPrmLst(cell); + + /* Initialize PHICH offset information */ + rgSCHCmnDlPhichOffsetInit(cell); + + /* Update the size of HARQ ACK/NACK feedback table */ + /* The array size is increased by 2 to have enough free indices, where other + * indices are busy waiting for HARQ feedback */ + cell->ackNackFdbkArrSize = rgSchTddANFdbkMapTbl[cell->ulDlCfgIdx] + 2; + + /* Initialize expected HARQ ACK/NACK feedback time */ + rgSCHCmnDlANFdbkInit(cell); + + /* Initialize UL association set index */ + if(cell->ulDlCfgIdx != 0) + { + rgSCHCmnDlKdashUlAscInit(cell); + } + + if (cfg->isCpDlExtend == TRUE) + { + cp = RG_SCH_CMN_EXT_CP; + noSymPerSlot = 6; + cell->splSubfrmCfg.dwPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].extDlDwPts; + + if ( cell->splSubfrmCfg.dwPts == 0 ) + { + cell->isDwPtsCnted = FALSE; + } + else + { + cell->isDwPtsCnted = TRUE; + } + + if(cfg->isCpUlExtend == TRUE) + { + cell->splSubfrmCfg.upPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].extDlExtUpPts; + } + else + { + cell->splSubfrmCfg.upPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].extDlNorUpPts; + } + } + else + { + cp = RG_SCH_CMN_NOR_CP; + noSymPerSlot = 7; + cell->splSubfrmCfg.dwPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].norDlDwPts; + cell->isDwPtsCnted = TRUE; + + if(cfg->isCpUlExtend == TRUE) + { + cell->splSubfrmCfg.upPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].norDlExtUpPts; + } + else + { + cell->splSubfrmCfg.upPts = + rgSchTddSplSubfrmInfoTbl[splSubfrmIdx].norDlNorUpPts; + } + } + + /* Initializing the cqiToEffTbl and cqiToTbsTbl for every CFI value */ + for(cfi = 1; cfi < RG_SCH_CMN_MAX_CFI; cfi++,cfiIdx++) + { + cellSch->dl.cqiToTbsTbl[0][cfi] = rgSchCmnCqiToTbs[0][cp][cfiIdx]; + cellSch->dl.cqiToEffTbl[0][cfi] = rgSchCmnEffTbl[0][cp][rgSchCmnAntIdx\ + [cell->numTxAntPorts]][cfiIdx]; + cellSch->dl.cqiToTbsTbl[1][cfi] = rgSchCmnCqiToTbs[1][cp][cfiIdx]; + cellSch->dl.cqiToEffTbl[1][cfi] = rgSchCmnEffTbl[1][cp][rgSchCmnAntIdx\ + [cell->numTxAntPorts]][cfiIdx]; + } + + /* Initializing the values of CFI parameters */ + if(cell->dynCfiCb.isDynCfiEnb) + { + /* If DCFI is enabled, current CFI value will start from 1 */ + cellSch->dl.currCfi = cellSch->dl.newCfi = 1; + } + else + { + /* If DCFI is disabled, current CFI value is set as default max allowed CFI value */ + cellSch->dl.currCfi = RGSCH_MIN(cell->dynCfiCb.maxCfi, cellSch->cfiCfg.cfi); + cellSch->dl.newCfi = cellSch->dl.currCfi; + } + + /* Include CRS REs while calculating Efficiency + * The number of Resource Elements occupied by CRS depends on Number of + * Antenna Ports. Please refer to Section 6.10.1 of 3GPP TS 36.211 V8.8.0. + * Also, please refer to Figures 6.10.1.2-1 and 6.10.1.2-2 for diagrammatic + * details of the same. Please note that PDCCH overlap symbols would not + * considered in CRS REs deduction */ + for (cfi = 1; cfi < RG_SCH_CMN_MAX_CFI; cfi++, numPdcchSym++) + { + cellSch->dl.noResPerRb[cfi] = (((noSymPerSlot * RG_SCH_CMN_NUM_SLOTS_PER_SF) + - numPdcchSym) *RB_SCH_CMN_NUM_SCS_PER_RB) - rgSchCmnNumResForCrs[cell->numTxAntPorts]; + } + + /* DwPTS Scheduling Changes Start */ + antPortIdx = (cell->numTxAntPorts == 1)? 0: + ((cell->numTxAntPorts == 2)? 1: 2); + + if (cp == RG_SCH_CMN_NOR_CP) + { + splSfIdx = (splSubfrmIdx == 4)? 1: 0; + } + else + { + splSfIdx = (splSubfrmIdx == 3)? 1: 0; + } + + numCrs = rgSchCmnDwptsCrs[splSfIdx][antPortIdx]; + + for (cfi = 1; cfi < RG_SCH_CMN_MAX_CFI-1; cfi++) + { + /* If CFI is 2 and Ant Port is 4, don't consider the sym 1 CRS REs */ + if (antPortIdx == 2 && cfi == 2) + { + numCrs -= 4; + } + cellSch->dl.numReDwPts[cfi] = ((cell->splSubfrmCfg.dwPts - cfi)* + RB_SCH_CMN_NUM_SCS_PER_RB) - numCrs; + } + /* DwPTS Scheduling Changes End */ + + if (cfg->maxDlBwPerUe == 0) + { + cellSch->dl.maxDlBwPerUe = RG_SCH_CMN_MAX_DL_BW_PERUE; + } + else + { + cellSch->dl.maxDlBwPerUe = cfg->maxDlBwPerUe; + } + if (cfg->maxDlRetxBw == 0) + { + cellSch->dl.maxDlRetxBw = RG_SCH_CMN_MAX_DL_RETX_BW; + } + else + { + cellSch->dl.maxDlRetxBw = cfg->maxDlRetxBw; + } + /* Fix: MUE_PERTTI_DL*/ + cellSch->dl.maxUePerDlSf = cfg->maxUePerDlSf; + cellSch->dl.maxUeNewTxPerTti = cfg->maxDlUeNewTxPerTti; + if (cfg->maxUePerDlSf == 0) + { + cellSch->dl.maxUePerDlSf = RG_SCH_CMN_MAX_UE_PER_DL_SF; + } + RG_SCH_RESET_HCSG_DL_PRB_CNTR(&cellSch->dl); + /*[ccpu00138609]-ADD- Configure the Max CCCH Counter */ + if (cfg->maxCcchPerDlSf > cfg->maxUePerDlSf) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "Invalid configuration !: " + "maxCcchPerDlSf %u > maxUePerDlSf %u", + cfg->maxCcchPerDlSf, cfg->maxUePerDlSf ); + + RETVALUE(RFAILED); + } + else if (!cfg->maxCcchPerDlSf) + { + /* ccpu00143032: maxCcchPerDlSf 0 means not configured by application + * hence setting to maxUePerDlSf. If maxCcchPerDlSf is 0 then scheduler + * does't consider CCCH allocation in MaxUePerTti cap. Hence more than + * 4UEs getting schduled & SCH expects >16 Hq PDUs in a TTI which causes + * FLE crash in PHY as PHY has limit of 16 max*/ + cellSch->dl.maxCcchPerDlSf = cfg->maxUePerDlSf; + } + else + { + cellSch->dl.maxCcchPerDlSf = cfg->maxCcchPerDlSf; + } + if (rgSCHCmnDlCnsdrCmnRt(cell, &cfg->dlCmnCodeRate) != ROK) + { + RETVALUE(RFAILED); + } + + /*ccpu00118273 - ADD - start */ + cmLListInit(&cellSch->dl.msg4RetxLst); +#ifdef RGR_V1 + cmLListInit(&cellSch->dl.ccchSduRetxLst); +#endif + +#ifdef RG_PHASE2_SCHED + if (cellSch->apisDlfs == NULLP) /* DFLS specific initialization */ + { + cellSch->apisDlfs = &rgSchDlfsSchdTbl[cfg->dlfsSchdType]; + } + if (cfg->dlfsCfg.isDlFreqSel) + { + ret = cellSch->apisDlfs->rgSCHDlfsCellCfg(cell, cfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + cellSch->dl.isDlFreqSel = cfg->dlfsCfg.isDlFreqSel; +#endif + + /* Power related configuration */ + ret = rgSCHPwrCellCfg(cell, cfg); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + + cellSch->dl.bcchTxPwrOffset = cfg->bcchTxPwrOffset; + cellSch->dl.pcchTxPwrOffset = cfg->pcchTxPwrOffset; + cellSch->dl.rarTxPwrOffset = cfg->rarTxPwrOffset; + cellSch->dl.phichTxPwrOffset = cfg->phichTxPwrOffset; + cellSch->dl.msg4pAVal = cfg->msg4pAVal; + RETVALUE(ROK); +} +#else /* LTE_TDD */ +/** + * @brief This function handles the configuration of cell for the first + * time by the scheduler. + * + * @details + * + * Function: rgSCHCmnDlRgrCellCfg + * Purpose: Configuration received is stored into the data structures + * Also, update the scheduler with the number of frames of + * RACH preamble transmission. + * + * Invoked by: BO and Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgrCellCfg* cfg + * @param[in] RgSchErrInfo* err + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlRgrCellCfg +( +RgSchCellCb *cell, +RgrCellCfg *cfg, +RgSchErrInfo *err +) +#else +PRIVATE S16 rgSCHCmnDlRgrCellCfg(cell, cfg, err) +RgSchCellCb *cell; +RgrCellCfg *cfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch; + U8 cp; + U8 numPdcchSym; + U8 noSymPerSlot; + U8 cfi; + U8 cfiIdx; + + TRC2(rgSCHCmnDlRgrCellCfg); + + cellSch = RG_SCH_CMN_GET_CELL(cell); + + /* Initialize the parameters with the ones received in the */ + /* configuration. */ + + /* Added matrix 'rgRaPrmblToRaFrmTbl' for computation of RA + * sub-frames from preamble format */ + cellSch->dl.numRaSubFrms = rgRaPrmblToRaFrmTbl[cell->rachCfg.preambleFormat]; + + /*[ccpu00138532]-ADD-fill the Msg4 Harq data */ + cell->dlHqCfg.maxMsg4HqTx = cfg->dlHqCfg.maxMsg4HqTx; + + /* Msg4 Tx Delay = (HARQ_RTT * MAX_MSG4_HARQ_RETX) + + 3 TTI (MAX L1+L2 processing delay at the UE) */ + cellSch->dl.msg4TxDelay = (cfg->dlHqCfg.maxMsg4HqTx-1) * + rgSchCmnHarqRtt[7] + 3; + + if (cell->bwCfg.dlTotalBw <= 10) + { + cfiIdx = 1; + numPdcchSym = 2; + } + else + { + cfiIdx = 0; + numPdcchSym = 1; + } + + if (cell->isCpDlExtend == TRUE) + { + cp = RG_SCH_CMN_EXT_CP; + noSymPerSlot = 6; + } + else + { + cp = RG_SCH_CMN_NOR_CP; + noSymPerSlot = 7; + } + + /* Initializing the cqiToEffTbl and cqiToTbsTbl for every CFI value */ + for(cfi = 1; cfi < RG_SCH_CMN_MAX_CFI; cfi++, cfiIdx++) + { + cellSch->dl.cqiToTbsTbl[0][cfi] = rgSchCmnCqiToTbs[0][cp][cfiIdx]; +#ifdef EMTC_ENABLE + cellSch->dl.emtcCqiToTbsTbl[0][cfi] = rgSchEmtcCmnCqiToTbs[0][cp][cfiIdx]; +#endif + cellSch->dl.cqiToEffTbl[0][cfi] = rgSchCmnEffTbl[0][cp][rgSchCmnAntIdx\ + [cell->numTxAntPorts]][cfiIdx]; + cellSch->dl.cqiToTbsTbl[1][cfi] = rgSchCmnCqiToTbs[1][cp][cfiIdx]; +#ifdef EMTC_ENABLE + cellSch->dl.emtcCqiToTbsTbl[1][cfi] = rgSchEmtcCmnCqiToTbs[1][cp][cfiIdx]; +#endif + cellSch->dl.cqiToEffTbl[1][cfi] = rgSchCmnEffTbl[1][cp][rgSchCmnAntIdx\ + [cell->numTxAntPorts]][cfiIdx]; + } + + /* Initializing the values of CFI parameters */ + if(cell->dynCfiCb.isDynCfiEnb) + { + /* If DCFI is enabled, current CFI value will start from 1 */ + cellSch->dl.currCfi = cellSch->dl.newCfi = 1; + } + else + { + /* If DCFI is disabled, current CFI value is set as default CFI value */ + cellSch->dl.currCfi = cellSch->cfiCfg.cfi; + cellSch->dl.newCfi = cellSch->dl.currCfi; + } + + /* Include CRS REs while calculating Efficiency + * The number of Resource Elements occupied by CRS depends on Number of + * Antenna Ports. Please refer to Section 6.10.1 of 3GPP TS 36.211 V8.8.0. + * Also, please refer to Figures 6.10.1.2-1 and 6.10.1.2-2 for diagrammatic + * details of the same. Please note that PDCCH overlap symbols would not + * considered in CRS REs deduction */ + for (cfi = 1; cfi < RG_SCH_CMN_MAX_CFI; cfi++, numPdcchSym++) + { + cellSch->dl.noResPerRb[cfi] = (((noSymPerSlot * RG_SCH_CMN_NUM_SLOTS_PER_SF) + - numPdcchSym) * RB_SCH_CMN_NUM_SCS_PER_RB) - rgSchCmnNumResForCrs[cell->numTxAntPorts]; + } + + if (cfg->maxDlBwPerUe == 0) + { + cellSch->dl.maxDlBwPerUe = RG_SCH_CMN_MAX_DL_BW_PERUE; + } + else + { + cellSch->dl.maxDlBwPerUe = cfg->maxDlBwPerUe; + } + if (cfg->maxDlRetxBw == 0) + { + cellSch->dl.maxDlRetxBw = RG_SCH_CMN_MAX_DL_RETX_BW; + } + else + { + cellSch->dl.maxDlRetxBw = cfg->maxDlRetxBw; + } + + /* Fix: MUE_PERTTI_DL*/ + cellSch->dl.maxUePerDlSf = cfg->maxUePerDlSf; + cellSch->dl.maxUeNewTxPerTti = cfg->maxDlUeNewTxPerTti; + if (cfg->maxUePerDlSf == 0) + { + cellSch->dl.maxUePerDlSf = RG_SCH_CMN_MAX_UE_PER_DL_SF; + } + /* Fix: MUE_PERTTI_DL syed validating Cell Configuration */ + if (cellSch->dl.maxUePerDlSf < cellSch->dl.maxUeNewTxPerTti) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "FAILED MaxUePerDlSf(%u) < MaxDlUeNewTxPerTti(%u)", + cellSch->dl.maxUePerDlSf, + cellSch->dl.maxUeNewTxPerTti); + RETVALUE(RFAILED); + } + /*[ccpu00138609]-ADD- Configure the Max CCCH Counter */ + if (cfg->maxCcchPerDlSf > cfg->maxUePerDlSf) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Invalid configuration !: " + "maxCcchPerDlSf %u > maxUePerDlSf %u", + cfg->maxCcchPerDlSf, cfg->maxUePerDlSf ); + + RETVALUE(RFAILED); + } + else if (!cfg->maxCcchPerDlSf) + { + /* ccpu00143032: maxCcchPerDlSf 0 means not configured by application + * hence setting to maxUePerDlSf. If maxCcchPerDlSf is 0 then scheduler + * does't consider CCCH allocation in MaxUePerTti cap. Hence more than + * 4UEs getting schduled & SCH expects >16 Hq PDUs in a TTI which causes + * FLE crash in PHY as PHY has limit of 16 max*/ + cellSch->dl.maxCcchPerDlSf = cfg->maxUePerDlSf; + } + else + { + cellSch->dl.maxCcchPerDlSf = cfg->maxCcchPerDlSf; + } + + + if (rgSCHCmnDlCnsdrCmnRt(cell, &cfg->dlCmnCodeRate) != ROK) + { + RETVALUE(RFAILED); + } + cmLListInit(&cellSch->dl.msg4RetxLst); +#ifdef RGR_V1 + cmLListInit(&cellSch->dl.ccchSduRetxLst); +#endif + +#ifdef RG_PHASE2_SCHED + if (cellSch->apisDlfs == NULLP) /* DFLS specific initialization */ + { + cellSch->apisDlfs = &rgSchDlfsSchdTbl[cfg->dlfsSchdType]; + } + if (cfg->dlfsCfg.isDlFreqSel) + { + ret = cellSch->apisDlfs->rgSCHDlfsCellCfg(cell, cfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + cellSch->dl.isDlFreqSel = cfg->dlfsCfg.isDlFreqSel; +#endif + + /* Power related configuration */ + ret = rgSCHPwrCellCfg(cell, cfg); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + + cellSch->dl.bcchTxPwrOffset = cfg->bcchTxPwrOffset; + cellSch->dl.pcchTxPwrOffset = cfg->pcchTxPwrOffset; + cellSch->dl.rarTxPwrOffset = cfg->rarTxPwrOffset; + cellSch->dl.phichTxPwrOffset = cfg->phichTxPwrOffset; + RG_SCH_RESET_HCSG_DL_PRB_CNTR(&cellSch->dl); + RETVALUE(ROK); +} +#endif /* LTE_TDD */ + +/*********************************************************** + * + * Func : rgSCHCmnUlCalcReqRbCeil + * + * Desc : Calculate RB required to satisfy 'bytes' for + * a given CQI. + * Returns number of RBs such that requirement + * is necessarily satisfied (does a 'ceiling' + * computation). + * + * Ret : Required RBs (U8) + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUlCalcReqRbCeil +( +U32 bytes, +U8 cqi, +RgSchCmnUlCell *cellUl +) +#else +PUBLIC U8 rgSCHCmnUlCalcReqRbCeil(bytes, cqi, cellUl) +U32 bytes; +U8 cqi; +RgSchCmnUlCell *cellUl; +#endif +{ + U32 numRe = RGSCH_CEIL((bytes * 8) * 1024, rgSchCmnUlCqiTbl[cqi].eff); + TRC2(rgSCHCmnUlCalcReqRbCeil); + RETVALUE((U8)RGSCH_CEIL(numRe, RG_SCH_CMN_UL_NUM_RE_PER_RB(cellUl))); +} + +/*********************************************************** + * + * Func : rgSCHCmnPrecompMsg3Vars + * + * Desc : Precomputes the following for msg3 allocation: + * 1. numSb and Imcs for msg size A + * 2. numSb and Imcs otherwise + * + * Ret : + * + * Notes: The corresponding vars in cellUl struct is filled + * up + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnPrecompMsg3Vars +( +RgSchCmnUlCell *cellUl, +U8 ccchCqi, +U16 msgSzA, +U8 sbSize, +Bool isEcp +) +#else +PRIVATE S16 rgSCHCmnPrecompMsg3Vars(cellUl, ccchCqi, msgSzA, sbSize, isEcp) +RgSchCmnUlCell *cellUl; +U8 ccchCqi; +U16 msgSzA; +U8 sbSize; +Bool isEcp; +#endif +{ + U8 numSb; + U8 ccchTbs; + U8 ccchMcs; + U8 numRb = 0; + U8 iTbs = 0; + U16 msg3GrntSz = 0; + + TRC2(rgSCHCmnPrecompMsg3Vars); + + if (ccchCqi > cellUl->max16qamCqi) + { + ccchCqi = cellUl->max16qamCqi; + } +/* #ifndef RG_SCH_CMN_EXP_CP_SUP For ECP Pick the index 1 */ + /* Fix */ + ccchTbs = rgSchCmnUlCqiToTbsTbl[(U8)isEcp][ccchCqi]; + ccchMcs = rgSCHCmnUlGetIMcsFrmITbs(ccchTbs, CM_LTE_UE_CAT_1); + + /* MCS should fit in 4 bits in RAR */ + if (ccchMcs >= 15) + { + ccchMcs = 15; + } + + /* Limit the ccchMcs to 15 as it + * can be inferred from 36.213, section 6.2 that msg3 imcs + * field is 4 bits. + * Since, UE doesn't exist right now, we use CAT_1 for ue + * category*/ + while((ccchMcs = (rgSCHCmnUlGetIMcsFrmITbs( + rgSchCmnUlCqiToTbsTbl[(U8)isEcp][ccchCqi],CM_LTE_UE_CAT_1)) + ) > + RG_SCH_CMN_MAX_MSG3_IMCS) + { + ccchCqi--; + } + + iTbs = rgSchCmnUlCqiToTbsTbl[(U8)isEcp][ccchCqi]; + + if (msgSzA < RGSCH_MIN_MSG3_GRNT_SZ) + { + RETVALUE(RFAILED); + } + numSb = RGSCH_CEIL(rgSCHCmnUlCalcReqRbCeil(msgSzA, ccchCqi, cellUl), sbSize); + + numRb = numSb * sbSize; + msg3GrntSz = 8 * msgSzA; + + while( (rgTbSzTbl[0][iTbs][numRb - 1]) < msg3GrntSz) + { + ++numSb; + numRb = numSb * sbSize; + } + while (rgSchCmnMult235Tbl[numSb].match != numSb) + { + ++numSb; + } + /* Reversed(Corrected) the assignment for preamble-GrpA + * Refer- TG36.321- section- 5.1.2*/ + cellUl->ra.prmblBNumSb = numSb; + cellUl->ra.prmblBIMcs = ccchMcs; + numSb = RGSCH_CEIL(rgSCHCmnUlCalcReqRbCeil(RGSCH_MIN_MSG3_GRNT_SZ, \ + ccchCqi, cellUl), + sbSize); + + numRb = numSb * sbSize; + msg3GrntSz = 8 * RGSCH_MIN_MSG3_GRNT_SZ; + while( (rgTbSzTbl[0][iTbs][numRb - 1]) < msg3GrntSz) + { + ++numSb; + numRb = numSb * sbSize; + } + while (rgSchCmnMult235Tbl[numSb].match != numSb) + { + ++numSb; + } + /* Reversed(Corrected) the assignment for preamble-GrpA + * Refer- TG36.321- section- 5.1.2*/ + cellUl->ra.prmblANumSb = numSb; + cellUl->ra.prmblAIMcs = ccchMcs; + RETVALUE(ROK); +} + +PUBLIC U32 gPrntPucchDet=0; + +#ifdef LTE_TDD +/*********************************************************** + * + * Func : rgSCHCmnUlCalcAvailBw + * + * Desc : Calculates bandwidth available for PUSCH scheduling. + * + * Ret : S16 (ROK/RFAILED) + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlCalcAvailBw +( +RgSchCellCb *cell, +RgrCellCfg *cellCfg, +U8 cfi, +U8 *rbStartRef, +U8 *bwAvailRef +) +#else +PRIVATE S16 rgSCHCmnUlCalcAvailBw(cell, cellCfg, cfi, rbStartRef, bwAvailRef) +RgSchCellCb *cell; +RgrCellCfg *cellCfg; +U8 cfi; +U8 *rbStartRef; +U8 *bwAvailRef; +#endif +{ + U8 c = 3; + U8 ulBw = cell->bwCfg.ulTotalBw; + U8 n2Rb = cell->pucchCfg.resourceSize; + U8 pucchDeltaShft = cell->pucchCfg.deltaShift; + U16 n1Pucch = cell->pucchCfg.n1PucchAn; + U8 n1Cs = cell->pucchCfg.cyclicShift; + + U8 n1PerRb; + U8 totalCce; + U16 n1Max; + U8 n1Rb; + U32 mixedRb; + U8 exclRb; /* RBs to exclude */ + U8 n1RbPart; + U8 puschRbStart; + /* To avoid PUCCH and PUSCH collision issue */ + U8 P; + U8 n1PlusOne; + U8 mi; + /* Maximum value of M as per Table 10.1-1 */ + U8 M[RGSCH_MAX_TDD_UL_DL_CFG] = {1, 2, 4, 3, 4, 9, 1}; + + TRC2(rgSCHCmnUlCalcAvailBw); + + if (cell->isCpUlExtend) + { + c = 2; + } + + n1PerRb = c * 12 / pucchDeltaShft; /* 12/18/36 */ + + /* Considering the max no. of CCEs for PUSCH BW calculation + * based on min mi value */ + if (cell->ulDlCfgIdx == 0 || cell->ulDlCfgIdx == 6) + { + mi = 1; + } + else + { + mi = 0; + } + + totalCce = cell->dynCfiCb.cfi2NCceTbl[mi][cfi]; + + P = rgSCHCmnGetPValFrmCCE(cell, totalCce-1); + n1PlusOne = cell->rgSchTddNpValTbl[P + 1]; + n1Max = (M[cell->ulDlCfgIdx] - 1)*n1PlusOne + (totalCce-1) + n1Pucch; + + /* ccpu00129978- MOD- excluding RBs based on formula in section 5.4.3 in + * TS 36.211 */ + n1RbPart = (c*n1Cs)/pucchDeltaShft; + n1Rb = (n1Max - n1RbPart)/ n1PerRb; + mixedRb = RGSCH_CEIL(n1Cs, 8); /* same as 'mixedRb = n1Cs ? 1 : 0' */ + + /* get the total Number of RB's to be excluded for PUSCH */ + /* ccpu00137339 */ + if(n1Pucch < n1RbPart) + { + exclRb = n2Rb; + } + else + { + exclRb = n2Rb + mixedRb + n1Rb; /* RBs to exclude */ + } + puschRbStart = exclRb/2 + 1; + + /* Num of PUCCH RBs = puschRbStart*2 */ + if (puschRbStart * 2 >= ulBw) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"No bw available for PUSCH"); + RETVALUE(RFAILED); + } + + *rbStartRef = puschRbStart; + *bwAvailRef = ulBw - puschRbStart * 2; + + if(cell->pucchCfg.maxPucchRb !=0 && + (puschRbStart * 2 > cell->pucchCfg.maxPucchRb)) + { + cell->dynCfiCb.maxCfi = RGSCH_MIN(cfi-1, cell->dynCfiCb.maxCfi); + } + + RETVALUE(ROK); +} +#else + +/*********************************************************** + * + * Func : rgSCHCmnUlCalcAvailBw + * + * Desc : Calculates bandwidth available for PUSCH scheduling. + * + * Ret : S16 (ROK/RFAILED) + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlCalcAvailBw +( +RgSchCellCb *cell, +RgrCellCfg *cellCfg, +U8 cfi, +U8 *rbStartRef, +U8 *bwAvailRef +) +#else +PRIVATE S16 rgSCHCmnUlCalcAvailBw(cell, cellCfg, cfi, rbStartRef, bwAvailRef) +RgSchCellCb *cell; +RgrCellCfg *cellCfg; +U8 cfi; +U8 *rbStartRef; +U8 *bwAvailRef; +#endif +{ + U8 c = 3; + U8 ulBw = cell->bwCfg.ulTotalBw; + U8 n2Rb = cell->pucchCfg.resourceSize; + U8 pucchDeltaShft = cell->pucchCfg.deltaShift; + U16 n1Pucch = cell->pucchCfg.n1PucchAn; + U8 n1Cs = cell->pucchCfg.cyclicShift; + U8 n1PerRb; + U8 totalCce; + U16 n1Max; + U8 n1Rb; + U32 mixedRb; + U8 exclRb; /* RBs to exclude */ + U8 n1RbPart; + U8 puschRbStart; +#ifdef LTE_ADV + U16 numOfN3PucchRb; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); +#endif + + TRC2(rgSCHCmnUlCalcAvailBw); + + if (cell->isCpUlExtend) + { + c = 2; + } + + n1PerRb = c * 12 / pucchDeltaShft; /* 12/18/36 */ + + totalCce = cell->dynCfiCb.cfi2NCceTbl[0][cfi]; + + n1Max = n1Pucch + totalCce-1; + + /* ccpu00129978- MOD- excluding RBs based on formula in section 5.4.3 in + * TS 36.211 */ + n1RbPart = (c*n1Cs)/pucchDeltaShft; + n1Rb = (U8)((n1Max - n1RbPart) / n1PerRb); + mixedRb = RGSCH_CEIL(n1Cs, 8); /* same as 'mixedRb = n1Cs ? 1 : 0' */ + + /* get the total Number of RB's to be excluded for PUSCH */ + /* ccpu00137339 */ + if(n1Pucch < n1RbPart) + { + exclRb = n2Rb; + } + else + { + exclRb = n2Rb + mixedRb + n1Rb; /* RBs to exclude */ + } + /*Support for PUCCH Format 3*/ +#ifdef LTE_ADV + if (cell->isPucchFormat3Sptd) + { + numOfN3PucchRb = RGSCH_CEIL(cellSch->dl.maxUePerDlSf,5); + exclRb = exclRb + numOfN3PucchRb; + } +#endif + puschRbStart = exclRb/2 + 1; + + if(gPrntPucchDet) + { +#ifndef ALIGN_64BIT + printf("CA_DBG:: puschRbStart:n1Rb:mixedRb:n1PerRb:totalCce:n1Max:n1RbPart:n2Rb::[%d:%d] [%d:%d:%ld:%d:%d:%d:%d:%d]\n", + cell->crntTime.sfn, cell->crntTime.subframe, puschRbStart, n1Rb, mixedRb,n1PerRb, totalCce, n1Max, n1RbPart, n2Rb); +#else + printf("CA_DBG:: puschRbStart:n1Rb:mixedRb:n1PerRb:totalCce:n1Max:n1RbPart:n2Rb::[%d:%d] [%d:%d:%d:%d:%d:%d:%d:%d]\n", + cell->crntTime.sfn, cell->crntTime.subframe, puschRbStart, n1Rb, mixedRb,n1PerRb, totalCce, n1Max, n1RbPart, n2Rb); +#endif + } + + if (puschRbStart*2 >= ulBw) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"No bw available for PUSCH"); + RETVALUE(RFAILED); + } + + *rbStartRef = puschRbStart; + *bwAvailRef = ulBw - puschRbStart * 2; + + if(cell->pucchCfg.maxPucchRb !=0 && + (puschRbStart * 2 > cell->pucchCfg.maxPucchRb)) + { + cell->dynCfiCb.maxCfi = RGSCH_MIN(cfi-1, cell->dynCfiCb.maxCfi); + } + + RETVALUE(ROK); +} +#endif + + + +/*********************************************************** + * + * Func : rgSCHCmnUlCellInit + * + * Desc : Uplink scheduler initialisation for cell. + * + * Ret : S16 + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlCellInit +( + RgSchCellCb *cell, + RgrCellCfg *cellCfg + ) +#else +PRIVATE S16 rgSCHCmnUlCellInit(cell, cellCfg) + RgSchCellCb *cell; + RgrCellCfg *cellCfg; +#endif +{ + S16 ret; + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + U8 maxUePerUlSf = cellCfg->maxUePerUlSf; +#ifdef RGR_V1 + /* Added configuration for maximum number of MSG3s */ + U8 maxMsg3PerUlSf = cellCfg->maxMsg3PerUlSf; +#endif + U8 maxUlBwPerUe = cellCfg->maxUlBwPerUe; + U8 sbSize = cellCfg->puschSubBand.size; + U8 i; + U8 rbStart; + U8 bwAvail; + U8 cfi; + U8 maxSbPerUe; + U8 numSb; +#ifdef LTE_TDD + U16 ulDlCfgIdx = cell->ulDlCfgIdx; + /* [ccpu00127294]-MOD-Change the max Ul subfrms size in TDD */ + U8 maxSubfrms = 2 * rgSchTddNumUlSf[ulDlCfgIdx]; + U8 ulToDlMap[12] = {0}; /* maximum 6 Subframes in UL * 2 */ + U8 maxUlsubfrms = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx]\ + [RGSCH_NUM_SUB_FRAMES-1]; + U16 subfrm; + S8 dlIdx; +#else + U8 maxSubfrms = RG_SCH_CMN_UL_NUM_SF; +#endif +#ifdef LTE_L2_MEAS + U8 idx; +#endif + U8 iTbs; +#if (defined(LTE_L2_MEAS) ) + Inst inst = cell->instIdx; +#endif /* #if (defined(LTE_L2_MEAS) || defined(DEBUGP) */ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + + TRC2(rgSCHCmnUlCellInit); + + cellUl->maxUeNewTxPerTti = cellCfg->maxUlUeNewTxPerTti; + if (maxUePerUlSf == 0) + { + maxUePerUlSf = RG_SCH_CMN_MAX_UE_PER_UL_SF; + } +#ifdef RGR_V1 + if (maxMsg3PerUlSf == 0) + { + maxMsg3PerUlSf = RG_SCH_CMN_MAX_MSG3_PER_UL_SF; + } + /* fixed the problem while sending raRsp + * if maxMsg3PerUlSf is greater than + * RGSCH_MAX_RNTI_PER_RARNTI + * */ + if(maxMsg3PerUlSf > RGSCH_MAX_RNTI_PER_RARNTI) + { + maxMsg3PerUlSf = RGSCH_MAX_RNTI_PER_RARNTI; + } + + if(maxMsg3PerUlSf > maxUePerUlSf) + { + maxMsg3PerUlSf = maxUePerUlSf; + } + + /*cellUl->maxAllocPerUlSf = maxUePerUlSf + maxMsg3PerUlSf;*/ + /*Max MSG3 should be a subset of Max UEs*/ + cellUl->maxAllocPerUlSf = maxUePerUlSf; + cellUl->maxMsg3PerUlSf = maxMsg3PerUlSf; +#else + cellUl->maxAllocPerUlSf = maxUePerUlSf; +#endif + /* Fix: MUE_PERTTI_UL syed validating Cell Configuration */ + if (cellUl->maxAllocPerUlSf < cellUl->maxUeNewTxPerTti) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "FAILED: MaxUePerUlSf(%u) < MaxUlUeNewTxPerTti(%u)", + cellUl->maxAllocPerUlSf, + cellUl->maxUeNewTxPerTti); + RETVALUE(RFAILED); + } + +#ifdef LTE_L2_MEAS +#ifdef LTE_TDD + for(idx = 0; idx < RGSCH_SF_ALLOC_SIZE; idx++) +#else + for(idx = 0; idx < RGSCH_NUM_SUB_FRAMES; idx++) +#endif + { + + ret = rgSCHUtlAllocSBuf(inst, (Data **)&(cell->sfAllocArr[idx]. + ulUeInfo.ulAllocInfo), (cellUl->maxAllocPerUlSf * sizeof(RgInfUeUlAlloc))); + if (ret != ROK) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation failed "); + RETVALUE(ret); + } + } +#endif + if (maxUlBwPerUe == 0) + { + /* ccpu00139362- Setting to configured UL BW instead of MAX BW(100)*/ + maxUlBwPerUe = cell->bwCfg.ulTotalBw; + } + cellUl->maxUlBwPerUe = maxUlBwPerUe; + + /* FOR RG_SCH_CMN_EXT_CP_SUP */ + if (!cellCfg->isCpUlExtend) + { + cellUl->ulNumRePerRb = 12 * (14 - RGSCH_UL_SYM_DMRS_SRS); + } + else + { + cellUl->ulNumRePerRb = 12 * (12 - RGSCH_UL_SYM_DMRS_SRS); + } + + if (sbSize != rgSchCmnMult235Tbl[sbSize].match) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Invalid subband size %d", sbSize); + RETVALUE(RFAILED); + } + //Setting the subband size to 4 which is size of VRBG in 5GTF +#ifdef RG_5GTF + sbSize = MAX_5GTF_VRBG_SIZE; +#endif + + maxSbPerUe = maxUlBwPerUe / sbSize; + if (maxSbPerUe == 0) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnUlCellInit(): " + "maxUlBwPerUe/sbSize is zero"); + RETVALUE(RFAILED); + } + cellUl->maxSbPerUe = rgSchCmnMult235Tbl[maxSbPerUe].prvMatch; + + /* CQI related updations */ + if ((!RG_SCH_CMN_UL_IS_CQI_VALID(cellCfg->ulCmnCodeRate.ccchCqi)) + || (!RG_SCH_CMN_UL_IS_CQI_VALID(cellCfg->trgUlCqi.trgCqi))) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnUlCellInit(): " + "Invalid cqi"); + RETVALUE(RFAILED); + } + cellUl->dfltUlCqi = cellCfg->ulCmnCodeRate.ccchCqi; + + /* Changed the logic to determine maxUlCqi. + * For a 16qam UE, maxUlCqi is the CQI Index at which + * efficiency is as close as possible to RG_SCH_MAX_CODE_RATE_16QAM + * Refer to 36.213-8.6.1 */ + for (i = RG_SCH_CMN_UL_NUM_CQI - 1;i > 0; --i) + { + RLOG_ARG2(L_INFO,DBG_CELLID,cell->cellId, + "CQI %u:iTbs %u", + i, + rgSchCmnUlCqiToTbsTbl[cell->isCpUlExtend][i]); +#ifdef MAC_SCH_STATS + /* ccpu00128489 ADD Update mcs in hqFailStats here instead of at CRC + * since CQI to MCS mapping does not change. The only exception is for + * ITBS = 19 where the MCS can be 20 or 21 based on the UE cat. We + * choose 20, instead of 21, ie UE_CAT_3 */ + iTbs = rgSchCmnUlCqiToTbsTbl[cell->isCpUlExtend][i]; + RG_SCH_CMN_UL_TBS_TO_MCS(iTbs, hqFailStats.ulCqiStat[i - 1].mcs); +#endif + } + for (i = RG_SCH_CMN_UL_NUM_CQI - 1; i != 0; --i) + { + /* Fix for ccpu00123912*/ + iTbs = rgSchCmnUlCqiToTbsTbl[cell->isCpUlExtend][i]; + if (iTbs <= RGSCH_UL_16QAM_MAX_ITBS) /* corresponds to 16QAM */ + { + RLOG_ARG1(L_INFO,DBG_CELLID,cell->cellId, + "16 QAM CQI %u", i); + cellUl->max16qamCqi = i; + break; + } + } + +#ifdef EMTC_ENABLE + /* Precompute useful values for RA msg3 */ + ret = rgSCHCmnPrecompEmtcMsg3Vars(cellUl, cellCfg->ulCmnCodeRate.ccchCqi, + cell->rachCfg.msgSizeGrpA, sbSize, cell->isCpUlExtend); + if (ret != ROK) + { + RETVALUE(ret); + } +#endif + + /* Precompute useful values for RA msg3 */ + ret = rgSCHCmnPrecompMsg3Vars(cellUl, cellCfg->ulCmnCodeRate.ccchCqi, + cell->rachCfg.msgSizeGrpA, sbSize, cell->isCpUlExtend); + if (ret != ROK) + { + RETVALUE(ret); + } + + cellUl->sbSize = sbSize; + +#ifdef LTE_TDD + cellUl->numUlSubfrms = maxSubfrms; + + ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&cellUl->ulSfArr, + cellUl->numUlSubfrms * sizeof(RgSchUlSf)); + + if (ret != ROK) + { + cellUl->numUlSubfrms = 0; + RETVALUE(ret); + } + + /* store the DL subframe corresponding to the PUSCH offset + * in their respective UL subframe */ + for(i=0; i < RGSCH_NUM_SUB_FRAMES; i++) + { + if(rgSchTddPuschTxKTbl[ulDlCfgIdx][i] != 0) + { + subfrm = (i + rgSchTddPuschTxKTbl[ulDlCfgIdx][i]) % \ + RGSCH_NUM_SUB_FRAMES; + subfrm = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][subfrm]-1; + dlIdx = rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][i]-1; + RGSCH_ARRAY_BOUND_CHECK( cell->instIdx, ulToDlMap, subfrm); + ulToDlMap[subfrm] = dlIdx; + } + } + /* Copy the information in the remaining UL subframes based + * on number of HARQ processes */ + for(i=maxUlsubfrms; i < maxSubfrms; i++) + { + subfrm = i-maxUlsubfrms; + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, ulToDlMap, i); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, ulToDlMap, subfrm) + ulToDlMap[i] = ulToDlMap[subfrm]; + } +#endif + + for (cfi = 1; cfi < RG_SCH_CMN_MAX_CFI; cfi++) + { +#ifdef LTE_TDD + ret = rgSCHCmnUlCalcAvailBw(cell, cellCfg, cfi, &rbStart, &bwAvail); +#else + ret = rgSCHCmnUlCalcAvailBw(cell, cellCfg, cfi, &rbStart, &bwAvail); +#endif + if (ret != ROK) + { + RETVALUE(ret); + } + + if (cfi == 1) + { + cell->ulAvailBw = bwAvail; + } + + numSb = bwAvail/sbSize; + + cell->dynCfiCb.bwInfo[cfi].startRb = rbStart; + cell->dynCfiCb.bwInfo[cfi].numSb = numSb; + } + + if(0 == cell->dynCfiCb.maxCfi) + { + RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId, + "Incorrect Default CFI(%u), maxCfi(%u), maxPucchRb(%d)", + cellSch->cfiCfg.cfi, cell->dynCfiCb.maxCfi, + cell->pucchCfg.maxPucchRb); + + RETVALUE(RFAILED); + } + + /* DMRS values */ + cellUl->dmrsArrSize = cell->dynCfiCb.bwInfo[1].numSb; + ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&cellUl->dmrsArr, + cellUl->dmrsArrSize * sizeof(*cellUl->dmrsArr)); + if (ret != ROK) + { + RETVALUE(ret); + } + for (i = 0; i < cellUl->dmrsArrSize; ++i) + { + cellUl->dmrsArr[i] = cellCfg->puschSubBand.dmrs[i]; + } + + /* Init subframes */ + for (i = 0; i < maxSubfrms; ++i) + { + ret = rgSCHUtlUlSfInit(cell, &cellUl->ulSfArr[i], i, + cellUl->maxAllocPerUlSf); + if (ret != ROK) + { + for (; i != 0; --i) + { + rgSCHUtlUlSfDeinit(cell, &cellUl->ulSfArr[i-1]); + } + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(cellUl->dmrsArr)), + cellUl->dmrsArrSize * sizeof(*cellUl->dmrsArr)); +#ifdef LTE_TDD + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, + (Data **)(&(cellUl->ulSfArr)), maxSubfrms * sizeof(RgSchUlSf)); +#endif + RETVALUE(ret); + } + } + RG_SCH_RESET_HCSG_UL_PRB_CNTR(cellUl); + RETVALUE(ROK); +} + +/** + * @brief Scheduler processing on cell configuration. + * + * @details + * + * Function : rgSCHCmnRgrCellCfg + * + * This function does requisite initialisation + * and setup for scheduler1 when a cell is + * configured. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgrCellCfg *cellCfg + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrCellCfg +( +RgSchCellCb *cell, +RgrCellCfg *cellCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrCellCfg(cell, cellCfg, err) +RgSchCellCb *cell; +RgrCellCfg *cellCfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch; + TRC2(rgSCHCmnRgrCellCfg); + + /* As part of RGR cell configuration, validate the CRGCellCfg + * There is no trigger for crgCellCfg from SC1 */ + /* Removed failure check for Extended CP */ + + if (((ret = rgSCHUtlAllocSBuf(cell->instIdx, + (Data**)&(cell->sc.sch), (sizeof(RgSchCmnCell)))) != ROK)) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "Memory allocation FAILED"); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + cellSch = (RgSchCmnCell *)(cell->sc.sch); + cellSch->cfiCfg = cellCfg->cfiCfg; + cellSch->trgUlCqi.trgCqi = cellCfg->trgUlCqi.trgCqi; + /* Initialize the scheduler refresh timer queues */ + cellSch->tmrTqCp.nxtEnt = 0; + cellSch->tmrTqCp.tmrLen = RG_SCH_CMN_NUM_REFRESH_Q; + + /* RACHO Intialize the RACH ded Preamble Information */ + rgSCHCmnCfgRachDedPrm(cell); +#ifdef LTE_TDD + /* Initialize 'Np' value for each 'p' used for + * HARQ ACK/NACK reception */ + rgSCHCmnDlNpValInit(cell); +#endif + + /* Initialize 'Np' value for each 'p' used for + * HARQ ACK/NACK reception */ +#ifdef LTE_TDD + rgSCHCmnDlNpValInit(cell); +#endif + + /* Now perform uplink related initializations */ + ret = rgSCHCmnUlCellInit(cell, cellCfg); + if (ret != ROK) + { + /* There is no downlink deinit to be performed */ + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + ret = rgSCHCmnDlRgrCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + /* DL scheduler has no initializations to make */ + /* As of now DL scheduler always returns ROK */ + + rgSCHCmnGetDciFrmtSizes(cell); + rgSCHCmnGetCqiDciFrmt2AggrLvl(cell); +#ifdef EMTC_ENABLE + rgSCHCmnGetEmtcDciFrmtSizes(cell); + rgSCHCmnGetCqiEmtcDciFrmt2AggrLvl(cell); +#endif /* EMTC_ENABLE */ + +#ifdef EMTC_ENABLE + if(TRUE == cellCfg->emtcEnable) + { + cellSch->apisEmtcUl = &rgSchEmtcUlSchdTbl[0]; + ret = cellSch->apisEmtcUl->rgSCHRgrUlCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + RETVALUE(ret); + } + } +#endif + cellSch->apisUl = &rgSchUlSchdTbl[RG_SCH_CMN_GET_UL_SCHED_TYPE(cell)]; + ret = cellSch->apisUl->rgSCHRgrUlCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + RETVALUE(ret); + } +#ifdef EMTC_ENABLE + if(TRUE == cellCfg->emtcEnable) + { + cellSch->apisEmtcDl = &rgSchEmtcDlSchdTbl[0]; + ret = cellSch->apisEmtcDl->rgSCHRgrDlCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + RETVALUE(ret); + } + } +#endif + cellSch->apisDl = &rgSchDlSchdTbl[RG_SCH_CMN_GET_DL_SCHED_TYPE(cell)]; +#ifdef LTEMAC_SPS + /* Perform SPS specific initialization for the cell */ + ret = rgSCHCmnSpsCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + RETVALUE(ret); + } +#endif + ret = cellSch->apisDl->rgSCHRgrDlCellCfg(cell, cellCfg, err); + if (ret != ROK) + { + RETVALUE(ret); + } + rgSCHCmnInitVars(cell); + + RETVALUE(ROK); +} /* rgSCHCmnRgrCellCfg*/ + + +/** + * @brief This function handles the reconfiguration of cell. + * + * @details + * + * Function: rgSCHCmnRgrCellRecfg + * Purpose: Update the reconfiguration parameters. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return Void + * + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrCellRecfg +( +RgSchCellCb *cell, +RgrCellRecfg *recfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrCellRecfg(cell, recfg, err) +RgSchCellCb *cell; +RgrCellRecfg *recfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + + TRC2(rgSCHCmnRgrCellRecfg); + + if (recfg->recfgTypes & RGR_CELL_UL_CMNRATE_RECFG) + { + U8 oldCqi = cellUl->dfltUlCqi; + if (!RG_SCH_CMN_UL_IS_CQI_VALID(recfg->ulCmnCodeRate.ccchCqi)) + { + err->errCause = RGSCHERR_SCH_CFG; + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnRgrCellRecfg(): " + "Invalid cqi"); + RETVALUE(RFAILED); + } + cellUl->dfltUlCqi = recfg->ulCmnCodeRate.ccchCqi; + ret = rgSCHCmnPrecompMsg3Vars(cellUl, recfg->ulCmnCodeRate.ccchCqi, + cell->rachCfg.msgSizeGrpA, cellUl->sbSize, cell->isCpUlExtend); + if (ret != ROK) + { + cellUl->dfltUlCqi = oldCqi; + rgSCHCmnPrecompMsg3Vars(cellUl, recfg->ulCmnCodeRate.ccchCqi, + cell->rachCfg.msgSizeGrpA, cellUl->sbSize, cell->isCpUlExtend); + RETVALUE(ret); + } + } + + if (recfg->recfgTypes & RGR_CELL_DL_CMNRATE_RECFG) + { + if (rgSCHCmnDlCnsdrCmnRt(cell, &recfg->dlCmnCodeRate) != ROK) + { + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + } + +#ifdef EMTC_ENABLE + if(TRUE == cell->emtcEnable) + { + /* Invoke UL sched for cell Recfg */ + ret = cellSch->apisEmtcUl->rgSCHRgrUlCellRecfg(cell, recfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + + /* Invoke DL sched for cell Recfg */ + ret = cellSch->apisEmtcDl->rgSCHRgrDlCellRecfg(cell, recfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + /* Invoke UL sched for cell Recfg */ + ret = cellSch->apisUl->rgSCHRgrUlCellRecfg(cell, recfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + + /* Invoke DL sched for cell Recfg */ + ret = cellSch->apisDl->rgSCHRgrDlCellRecfg(cell, recfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + + if (recfg->recfgTypes & RGR_CELL_DLFS_RECFG) + { + ret = cellSch->apisDlfs->rgSCHDlfsCellRecfg(cell, recfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + cellSch->dl.isDlFreqSel = recfg->dlfsRecfg.isDlFreqSel; + } + + if (recfg->recfgTypes & RGR_CELL_PWR_RECFG) + { + ret = rgSCHPwrCellRecfg(cell, recfg); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlCellDeinit + * + * Desc : Uplink scheduler de-initialisation for cell. + * + * Ret : S16 + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlCellDeinit +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnUlCellDeinit(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + U8 ulSfIdx; +#ifdef LTE_TDD + U8 maxSubfrms = cellUl->numUlSubfrms; +#endif +#ifdef LTE_L2_MEAS + CmLList *lnk = NULLP; + RgSchL2MeasCb *measCb; +#endif + TRC2(rgSCHCmnUlCellDeinit); +#ifdef LTE_L2_MEAS +#ifdef LTE_TDD + for(ulSfIdx = 0; ulSfIdx < RGSCH_SF_ALLOC_SIZE; ulSfIdx++) +#else + for(ulSfIdx = 0; ulSfIdx < RGSCH_NUM_SUB_FRAMES; ulSfIdx++) +#endif + { + if(cell->sfAllocArr[ulSfIdx].ulUeInfo.ulAllocInfo != NULLP) + { + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, + (Data **)(&(cell->sfAllocArr[ulSfIdx].ulUeInfo.ulAllocInfo)), + cellUl->maxAllocPerUlSf * sizeof(RgInfUeUlAlloc)); + + /* ccpu00117052 - DEL - removed explicit NULLP assignment + as it is done in above utility function */ + } + } + /* Free the memory allocated to measCb */ + lnk = cell->l2mList.first; + while(lnk != NULLP) + { + measCb = (RgSchL2MeasCb *)lnk->node; + cmLListDelFrm(&cell->l2mList, lnk); + lnk = lnk->next; + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&measCb,\ + sizeof(RgSchL2MeasCb)); + } +#endif + if (cellUl->dmrsArr != NULLP) + { + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx,(Data **)(&(cellUl->dmrsArr)), + cellUl->dmrsArrSize * sizeof(*cellUl->dmrsArr)); + } + /* De-init subframes */ +#ifdef LTE_TDD + for (ulSfIdx = 0; ulSfIdx < maxSubfrms; ++ulSfIdx) +#else + for (ulSfIdx = 0; ulSfIdx < RG_SCH_CMN_UL_NUM_SF; ++ulSfIdx) +#endif + { + rgSCHUtlUlSfDeinit(cell, &cellUl->ulSfArr[ulSfIdx]); + } + +#ifdef LTE_TDD + if (cellUl->ulSfArr != NULLP) + { + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, + (Data **)(&(cellUl->ulSfArr)), maxSubfrms * sizeof(RgSchUlSf)); + } +#endif + + RETVOID; +} + +/** + * @brief Scheduler processing for cell delete. + * + * @details + * + * Function : rgSCHCmnCellDel + * + * This functions de-initialises and frees memory + * taken up by scheduler1 for the entire cell. + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnCellDel +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnCellDel(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnCellDel); + +#ifdef LTE_L2_MEAS + glblTtiCnt = 0; +#endif + if (cellSch == NULLP) + { + RETVOID; + } + /* Perform the deinit for the UL scheduler */ + rgSCHCmnUlCellDeinit(cell); +#ifdef EMTC_ENABLE + if(TRUE == cell->emtcEnable) + { + if (cellSch->apisEmtcUl) + { + cellSch->apisEmtcUl->rgSCHFreeUlCell(cell); + } + } +#endif + if (cellSch->apisUl) + { + /* api pointer checks added (here and below in + * this function). pl check. - antriksh */ + cellSch->apisUl->rgSCHFreeUlCell(cell); + } + + /* Perform the deinit for the DL scheduler */ + cmLListInit(&cellSch->dl.taLst); + if (cellSch->apisDl) + { + cellSch->apisDl->rgSCHFreeDlCell(cell); + } +#ifdef EMTC_ENABLE + if (cellSch->apisEmtcDl) + { + rgSCHEmtcInitTaLst(&cellSch->dl); + + cellSch->apisEmtcDl->rgSCHFreeDlCell(cell); + } +#endif + + /* DLFS de-initialization */ + if (cellSch->dl.isDlFreqSel && cellSch->apisDlfs) + { + cellSch->apisDlfs->rgSCHDlfsCellDel(cell); + } + + rgSCHPwrCellDel(cell); +#ifdef LTEMAC_SPS + rgSCHCmnSpsCellDel(cell); +#endif + + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&(cell->sc.sch)), (sizeof(RgSchCmnCell))); + RETVOID; +} /* rgSCHCmnCellDel */ + + +/** + * @brief This function validates QOS parameters for DL. + * + * @details + * + * Function: rgSCHCmnValidateDlQos + * Purpose: This function validates QOS parameters for DL. + * + * Invoked by: Scheduler + * + * @param[in] CrgLchQosCfg *dlQos + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnValidateDlQos +( +RgrLchQosCfg *dlQos +) +#else +PRIVATE S16 rgSCHCmnValidateDlQos(dlQos) +RgrLchQosCfg *dlQos; +#endif +{ + U8 qci = dlQos->qci; + + TRC2(rgSCHCmnValidateDlQos); + + if ( qci < RG_SCH_CMN_MIN_QCI || qci > RG_SCH_CMN_MAX_QCI ) + { + RETVALUE(RFAILED); + } + + if ((qci >= RG_SCH_CMN_GBR_QCI_START) && + (qci <= RG_SCH_CMN_GBR_QCI_END)) + { + if ((dlQos->mbr == 0) || (dlQos->mbr < dlQos->gbr)) + { + RETVALUE(RFAILED); + } + } + RETVALUE(ROK); +} + +/** + * @brief Scheduler invocation on logical channel addition. + * + * @details + * + * Function : rgSCHCmnRgrLchCfg + * + * This functions does required processing when a new + * (dedicated) logical channel is added. Assumes lcg + * pointer in ulLc is set. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlLcCb *dlLc + * @param[int] RgrLchCfg *lcCfg + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrLchCfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlLcCb *dlLc, +RgrLchCfg *lcCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrLchCfg(cell, ue, dlLc, lcCfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlLcCb *dlLc; +RgrLchCfg *lcCfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnRgrLchCfg); + + ret = rgSCHUtlAllocSBuf(cell->instIdx, + (Data**)&((dlLc)->sch), (sizeof(RgSchCmnDlSvc))); + if (ret != ROK) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnRgrLchCfg(): " + "SCH struct alloc failed for CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + if(lcCfg->lcType != CM_LTE_LCH_DCCH) + { + ret = rgSCHCmnValidateDlQos(&lcCfg->dlInfo.dlQos); + if (ret != ROK) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"rgSchCmnCrgLcCfg(): " + "DlQos validation failed for CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + /* Perform DL service activation in the scheduler */ + ((RgSchCmnDlSvc *)(dlLc->sch))->qci = lcCfg->dlInfo.dlQos.qci; + ((RgSchCmnDlSvc *)(dlLc->sch))->prio = rgSchCmnDlQciPrio[lcCfg->dlInfo.dlQos.qci - 1]; + ((RgSchCmnDlSvc *)(dlLc->sch))->gbr = (lcCfg->dlInfo.dlQos.gbr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + ((RgSchCmnDlSvc *)(dlLc->sch))->mbr = (lcCfg->dlInfo.dlQos.mbr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + } + else + { + /*assigning highest priority to DCCH */ + ((RgSchCmnDlSvc *)(dlLc->sch))->prio=RG_SCH_CMN_DCCH_PRIO; + } + dlLc->ue = ue; + dlLc->lcType=lcCfg->lcType; + +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + ret = cellSch->apisEmtcDl->rgSCHRgrDlLcCfg(cell, ue,dlLc ,lcCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + ret = cellSch->apisDl->rgSCHRgrDlLcCfg(cell, ue, dlLc, lcCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + ret = cellSch->apisEmtcUl->rgSCHRgrUlLcCfg(cell, ue, lcCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + ret = cellSch->apisUl->rgSCHRgrUlLcCfg(cell, ue, lcCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + +#ifdef LTE_ADV + if (ue->numSCells) + { + rgSCHSCellDlLcCfg(cell, ue, dlLc); + } +#endif + + +#ifdef LTEMAC_SPS + if(lcCfg->dlInfo.dlSpsCfg.isSpsEnabled) + { + /* Invoke SPS module if SPS is enabled for the service */ + ret = rgSCHCmnSpsDlLcCfg(cell, ue, dlLc, lcCfg, err); + if (ret != ROK) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "rgSchCmnRgrLchCfg(): " + "SPS configuration failed for DL LC for CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(RFAILED); + } + } +#endif + + RETVALUE(ROK); +} + +/** + * @brief Scheduler invocation on logical channel addition. + * + * @details + * + * Function : rgSCHCmnRgrLchRecfg + * + * This functions does required processing when an existing + * (dedicated) logical channel is reconfigured. Assumes lcg + * pointer in ulLc is set to the old value. + * Independent of whether new LCG is meant to be configured, + * the new LCG scheduler information is accessed and possibly modified. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlLcCb *dlLc + * @param[int] RgrLchRecfg *lcRecfg + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrLchRecfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlLcCb *dlLc, +RgrLchRecfg *lcRecfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrLchRecfg(cell, ue, dlLc, lcRecfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlLcCb *dlLc; +RgrLchRecfg *lcRecfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnRgrLchRecfg) + + if(dlLc->lcType != CM_LTE_LCH_DCCH) + { + ret = rgSCHCmnValidateDlQos(&lcRecfg->dlRecfg.dlQos); + + if (ret != ROK) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "DlQos validation failed for CRNTI:%d LCID:%d",ue->ueId,lcRecfg->lcId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + if (((RgSchCmnDlSvc *)(dlLc->sch))->qci != lcRecfg->dlRecfg.dlQos.qci) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "Qci, hence lc Priority change " + "not supported for CRNTI:%d LCID:%d",ue->ueId,lcRecfg->lcId); + err->errCause = RGSCHERR_SCH_CFG; + RETVALUE(ret); + } + ((RgSchCmnDlSvc *)(dlLc->sch))->gbr = (lcRecfg->dlRecfg.dlQos.gbr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + ((RgSchCmnDlSvc *)(dlLc->sch))->mbr = (lcRecfg->dlRecfg.dlQos.mbr * \ + RG_SCH_CMN_REFRESH_TIME)/100; + } + else + { + /*assigning highest priority to DCCH */ + ((RgSchCmnDlSvc *)(dlLc->sch))->prio = RG_SCH_CMN_DCCH_PRIO; + } + +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + ret = cellSch->apisEmtcDl->rgSCHRgrDlLcRecfg(cell, ue, dlLc, lcRecfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + ret = cellSch->apisEmtcUl->rgSCHRgrUlLcRecfg(cell, ue, lcRecfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + ret = cellSch->apisDl->rgSCHRgrDlLcRecfg(cell, ue, dlLc, lcRecfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + ret = cellSch->apisUl->rgSCHRgrUlLcRecfg(cell, ue, lcRecfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + +#ifdef LTEMAC_SPS + if (lcRecfg->recfgTypes & RGR_DL_LC_SPS_RECFG) + { + /* Invoke SPS module if SPS is enabled for the service */ + if(lcRecfg->dlRecfg.dlSpsRecfg.isSpsEnabled) + { + ret = rgSCHCmnSpsDlLcRecfg(cell, ue, dlLc, lcRecfg, err); + if (ret != ROK) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"SPS re-configuration not " + "supported for dlLC Ignore this CRNTI:%d LCID:%d",ue->ueId,lcRecfg->lcId); + } + } + RETVALUE(ROK); + } +#endif + + RETVALUE(ROK); +} + +/** + * @brief Scheduler invocation on logical channel addition. + * + * @details + * + * Function : rgSCHCmnRgrLcgCfg + * + * This functions does required processing when a new + * (dedicated) logical channel is added. Assumes lcg + * pointer in ulLc is set. + * + * @param[in] RgSchCellCb *cell, + * @param[in] RgSchUeCb *ue, + * @param[in] RgSchLcgCb *lcg, + * @param[in] RgrLcgCfg *lcgCfg, + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrLcgCfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchLcgCb *lcg, +RgrLcgCfg *lcgCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrLcgCfg(cell, ue, lcg, lcgCfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchLcgCb *lcg; +RgrLcgCfg *lcgCfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnLcg *ulLcg = ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgCfg->ulInfo.lcgId].sch)); + + TRC2(rgSCHCmnRgrLcgCfg); + + ulLcg->cfgdGbr = (lcgCfg->ulInfo.gbr * RG_SCH_CMN_REFRESH_TIME)/100; + ulLcg->effGbr = ulLcg->cfgdGbr; + ulLcg->deltaMbr = ((lcgCfg->ulInfo.mbr - lcgCfg->ulInfo.gbr) * RG_SCH_CMN_REFRESH_TIME)/100; + ulLcg->effDeltaMbr = ulLcg->deltaMbr; + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + ret = cellSch->apisEmtcUl->rgSCHRgrUlLcgCfg(cell, ue, lcg, lcgCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + ret = cellSch->apisUl->rgSCHRgrUlLcgCfg(cell, ue, lcg, lcgCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + if (RGSCH_IS_GBR_BEARER(ulLcg->cfgdGbr)) + { + /* Indicate MAC that this LCG is GBR LCG */ + rgSCHUtlBuildNSendLcgReg(cell, ue->ueId, lcgCfg->ulInfo.lcgId, TRUE); + } + RETVALUE(ROK); +} + +/** + * @brief Scheduler invocation on logical channel addition. + * + * @details + * + * Function : rgSCHCmnRgrLcgRecfg + * + * This functions does required processing when a new + * (dedicated) logical channel is added. Assumes lcg + * pointer in ulLc is set. + * + * @param[in] RgSchCellCb *cell, + * @param[in] RgSchUeCb *ue, + * @param[in] RgSchLcgCb *lcg, + * @param[in] RgrLcgRecfg *reCfg, + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrLcgRecfg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchLcgCb *lcg, +RgrLcgRecfg *reCfg, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnRgrLcgRecfg(cell, ue, lcg, reCfg, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchLcgCb *lcg; +RgrLcgRecfg *reCfg; +RgSchErrInfo *err; +#endif +{ + S16 ret; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnLcg *ulLcg = ((RgSchCmnLcg *)(ue->ul.lcgArr[reCfg->ulRecfg.lcgId].sch)); + + TRC2(rgSCHCmnRgrLcgRecfg); + + ulLcg->cfgdGbr = (reCfg->ulRecfg.gbr * RG_SCH_CMN_REFRESH_TIME)/100; + ulLcg->effGbr = ulLcg->cfgdGbr; + ulLcg->deltaMbr = ((reCfg->ulRecfg.mbr - reCfg->ulRecfg.gbr) * RG_SCH_CMN_REFRESH_TIME)/100; + ulLcg->effDeltaMbr = ulLcg->deltaMbr; + +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + ret = cellSch->apisEmtcUl->rgSCHRgrUlLcgRecfg(cell, ue, lcg, reCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + else +#endif + { + ret = cellSch->apisUl->rgSCHRgrUlLcgRecfg(cell, ue, lcg, reCfg, err); + if (ret != ROK) + { + RETVALUE(RFAILED); + } + } + if (RGSCH_IS_GBR_BEARER(ulLcg->cfgdGbr)) + { + /* Indicate MAC that this LCG is GBR LCG */ + rgSCHUtlBuildNSendLcgReg(cell, ue->ueId, reCfg->ulRecfg.lcgId, TRUE); + } + else + { + /* In case of RAB modification */ + rgSCHUtlBuildNSendLcgReg(cell, ue->ueId, reCfg->ulRecfg.lcgId, FALSE); + } + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnRgrLchDel + * + * Desc : Scheduler handling for a (dedicated) + * uplink logical channel being deleted. + * + * Ret : + * + * Notes: + * + * File : + **********************************************************/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnRgrLchDel +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteLcId lcId, +U8 lcgId +) +#else +PUBLIC S16 rgSCHCmnRgrLchDel(cell, ue, lcId, lcgId) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteLcId lcId; +U8 lcgId; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnRgrLchDel); +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHRgrUlLchDel(cell, ue, lcId, lcgId); + } + else +#endif + { + cellSch->apisUl->rgSCHRgrUlLchDel(cell, ue, lcId, lcgId); + } + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnLcgDel + * + * Desc : Scheduler handling for a (dedicated) + * uplink logical channel being deleted. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnLcgDel +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchLcgCb *lcg +) +#else +PUBLIC Void rgSCHCmnLcgDel(cell, ue, lcg) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchLcgCb *lcg; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnLcg *lcgCmn = RG_SCH_CMN_GET_UL_LCG(lcg); + TRC2(rgSCHCmnLcgDel); + + if (lcgCmn == NULLP) + { + RETVOID; + } + + if (RGSCH_IS_GBR_BEARER(lcgCmn->cfgdGbr)) + { + /* Indicate MAC that this LCG is GBR LCG */ + rgSCHUtlBuildNSendLcgReg(cell, ue->ueId, lcg->lcgId, FALSE); + } + +#ifdef LTEMAC_SPS + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlLcgDel(cell, ue, lcg); + } +#endif /* LTEMAC_SPS */ + + lcgCmn->effGbr = 0; + lcgCmn->reportedBs = 0; + lcgCmn->cfgdGbr = 0; + /* set lcg bs to 0. Deletion of control block happens + * at the time of UE deletion. */ + lcgCmn->bs = 0; +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHFreeUlLcg(cell, ue, lcg); + } + else +#endif + { + cellSch->apisUl->rgSCHFreeUlLcg(cell, ue, lcg); + } + RETVOID; +} + + +/** + * @brief This function deletes a service from scheduler. + * + * @details + * + * Function: rgSCHCmnFreeDlLc + * Purpose: This function is made available through a FP for + * making scheduler aware of a service being deleted from UE. + * + * Invoked by: BO and Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ue + * @param[in] RgSchDlLcCb* svc + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnFreeDlLc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlLcCb *svc +) +#else +PUBLIC Void rgSCHCmnFreeDlLc(cell, ue, svc) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlLcCb *svc; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnFreeDlLc); + if (svc->sch == NULLP) + { + RETVOID; + } +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + cellSch->apisEmtcDl->rgSCHFreeDlLc(cell, ue, svc); + } + else +#endif + { + cellSch->apisDl->rgSCHFreeDlLc(cell, ue, svc); + } + +#ifdef LTE_ADV + if (ue->numSCells) + { + rgSCHSCellDlLcDel(cell, ue, svc); + } +#endif + +#ifdef LTEMAC_SPS + /* If SPS service, invoke SPS module */ + if (svc->dlLcSpsCfg.isSpsEnabled) + { + rgSCHCmnSpsDlLcDel(cell, ue, svc); + } +#endif + + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, + (Data**)(&(svc->sch)), (sizeof(RgSchCmnDlSvc))); + +#ifdef LTE_ADV + rgSCHLaaDeInitDlLchCb(cell, svc); +#endif + + RETVOID; +} + +#ifdef RGR_V1 + +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH SDURetx Allocations. + * + * @details + * + * Function: rgSCHCmnDlCcchSduRetxFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH Retx Allocations. + * Scans through the scheduled list of ccchSdu retrans + * fills the corresponding pdcch, adds the hqProc to + * the corresponding SubFrm and removes the hqP from + * cells retx List. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchSduRetxFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchSduRetxFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchDlRbAlloc *rbAllocInfo; + RgSchDlHqProcCb *hqP; + RgSchUeCb *ue; + TRC2(rgSCHCmnDlCcchSduRetxFnlz); + + /* Traverse through the Scheduled Retx List */ + node = allocInfo->ccchSduAlloc.schdCcchSduRetxLst.first; + while (node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + ue = hqP->hqE->ue; + rbAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell); + node = node->next; + rgSCHCmnFillHqPPdcch(cell, rbAllocInfo, hqP); + + /* Remove the HqP from cell's ccchSduRetxLst */ + cmLListDelFrm(&cmnCellDl->ccchSduRetxLst, &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)NULLP; + + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + rgSCHCmnDlUeResetTemp(ue, hqP); + } + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + node = allocInfo->ccchSduAlloc.nonSchdCcchSduRetxLst.first; + while(node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + ue = hqP->hqE->ue; + node = node->next; + /* reset the UE allocation Information */ + rgSCHCmnDlUeResetTemp(ue, hqP); + } + RETVOID; +} +#endif +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH Retx Allocations. + * + * @details + * + * Function: rgSCHCmnDlCcchRetxFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH Retx Allocations. + * Scans through the scheduled list of msg4 retrans + * fills the corresponding pdcch, adds the hqProc to + * the corresponding SubFrm and removes the hqP from + * cells retx List. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchRetxFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchRetxFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchDlRbAlloc *rbAllocInfo; + RgSchDlHqProcCb *hqP; + RgSchRaCb *raCb; + TRC2(rgSCHCmnDlCcchRetxFnlz); + + /* Traverse through the Scheduled Retx List */ + node = allocInfo->msg4Alloc.schdMsg4RetxLst.first; + while (node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + raCb = hqP->hqE->raCb; + rbAllocInfo = &raCb->rbAllocInfo; + node = node->next; + rgSCHCmnFillHqPPdcch(cell, rbAllocInfo, hqP); + + /* Remove the HqP from cell's msg4RetxLst */ + cmLListDelFrm(&cmnCellDl->msg4RetxLst, &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)NULLP; + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + cmMemset((U8 *)rbAllocInfo, (U8)0, sizeof(*rbAllocInfo)); + rgSCHCmnDlHqPResetTemp(hqP); + } + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + node = allocInfo->msg4Alloc.nonSchdMsg4RetxLst.first; + while(node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + raCb = hqP->hqE->raCb; + node = node->next; + cmMemset((U8 *)&raCb->rbAllocInfo, (U8)0, sizeof(raCb->rbAllocInfo)); + rgSCHCmnDlHqPResetTemp(hqP); + } + RETVOID; +} + +#ifdef RGR_V1 +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH SDU tx Allocations. + * + * @details + * + * Function: rgSCHCmnDlCcchSduTxFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH tx Allocations. + * Scans through the scheduled list of CCCH SDU trans + * fills the corresponding pdcch, adds the hqProc to + * the corresponding SubFrm and removes the hqP from + * cells tx List. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchSduTxFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchSduTxFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchUeCb *ueCb; + RgSchDlRbAlloc *rbAllocInfo; + RgSchDlHqProcCb *hqP; + RgSchLchAllocInfo lchSchdData; + TRC2(rgSCHCmnDlCcchSduTxFnlz); + + /* Traverse through the Scheduled Retx List */ + node = allocInfo->ccchSduAlloc.schdCcchSduTxLst.first; + while (node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + ueCb = hqP->hqE->ue; + node = node->next; + rbAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ueCb, cell); + + /* fill the pdcch and HqProc */ + rgSCHCmnFillHqPPdcch(cell, rbAllocInfo, hqP); + + /* Remove the raCb from cell's toBeSchdLst */ + cmLListDelFrm(&cell->ccchSduUeLst, &ueCb->ccchSduLnk); + ueCb->ccchSduLnk.node = (PTR)NULLP; + + /* Fix : Resetting this required to avoid complication + * in reestablishment case */ + ueCb->dlCcchInfo.bo = 0; + + /* Indicate DHM of the CCCH LC scheduling */ + hqP->tbInfo[0].contResCe = NOTPRSNT; + lchSchdData.lcId = 0; + lchSchdData.schdData = hqP->tbInfo[0].ccchSchdInfo.totBytes - + (RGSCH_MSG4_HDRSIZE); + rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, &hqP->tbInfo[0]); + + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + rgSCHCmnDlUeResetTemp(ueCb, hqP); + } + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + node = allocInfo->ccchSduAlloc.nonSchdCcchSduTxLst.first; + while(node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + ueCb = hqP->hqE->ue; + node = node->next; + /* Release HqProc */ + rgSCHDhmRlsHqpTb(hqP, 0, FALSE); + /*Fix: Removing releasing of TB1 as it will not exist for CCCH SDU and hence caused a crash*/ + /*rgSCHDhmRlsHqpTb(hqP, 1, FALSE);*/ + /* reset the UE allocation Information */ + rgSCHCmnDlUeResetTemp(ueCb, hqP); + } + RETVOID; +} + +#endif +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH tx Allocations. + * + * @details + * + * Function: rgSCHCmnDlCcchTxFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested + * CCCH tx Allocations. + * Scans through the scheduled list of msg4 trans + * fills the corresponding pdcch, adds the hqProc to + * the corresponding SubFrm and removes the hqP from + * cells tx List. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCcchTxFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlCcchTxFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + RgSchRaCb *raCb; + RgSchDlRbAlloc *rbAllocInfo; + RgSchDlHqProcCb *hqP; + RgSchLchAllocInfo lchSchdData; + TRC2(rgSCHCmnDlCcchTxFnlz); + + /* Traverse through the Scheduled Retx List */ + node = allocInfo->msg4Alloc.schdMsg4TxLst.first; + while (node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + raCb = hqP->hqE->raCb; + node = node->next; + rbAllocInfo = &raCb->rbAllocInfo; + + /* fill the pdcch and HqProc */ + rgSCHCmnFillHqPPdcch(cell, rbAllocInfo, hqP); + /* MSG4 Fix Start */ + + rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb); + /* MSG4 Fix End */ + + /* Indicate DHM of the CCCH LC scheduling */ + lchSchdData.lcId = 0; + lchSchdData.schdData = hqP->tbInfo[0].ccchSchdInfo.totBytes - + (RGSCH_MSG4_HDRSIZE + RGSCH_CONT_RESID_SIZE); + /* TRansmitting presence of cont Res CE across MAC-SCH interface to + * identify CCCH SDU transmissions which need to be done + * without the + * contention resolution CE*/ + hqP->tbInfo[0].contResCe = PRSNT_NODEF; + /*Dont add lc if only cont res CE is being transmitted*/ + if(raCb->dlCcchInfo.bo) + { + rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, &hqP->tbInfo[0]); + } + else + { + } + /* Fix: syed dlAllocCb reset should be performed. + * zombie info in dlAllocCb leading to crash rbNum wraparound */ + cmMemset((U8 *)&raCb->rbAllocInfo, (U8)0, sizeof(raCb->rbAllocInfo)); + rgSCHCmnDlHqPResetTemp(hqP); + } + node = allocInfo->msg4Alloc.nonSchdMsg4TxLst.first; + while(node) + { + hqP = (RgSchDlHqProcCb *)(node->node); + raCb = hqP->hqE->raCb; + node = node->next; + rbAllocInfo = &raCb->rbAllocInfo; + /* Release HqProc */ + rgSCHDhmRlsHqpTb(hqP, 0, FALSE); + /*Fix: Removing releasing of TB1 as it will not exist for MSG4 and hence caused a crash*/ + /* rgSCHDhmRlsHqpTb(hqP, 1, FALSE);*/ + /* reset the UE allocation Information */ + cmMemset((U8 *)rbAllocInfo, (U8)0, sizeof(*rbAllocInfo)); + rgSCHCmnDlHqPResetTemp(hqP); + } + + RETVOID; +} +/* R8 Upgrade */ +/** + * @brief This function calculates the BI Index to be sent in the Bi header + * field. + * + * @details + * Function: rgSCHCmnGetBiIndex + * Purpose: This function Processes utilizes the previous BI time value + * calculated and the difference last BI sent time and current time. To + * calculate the latest BI Index. It also considers the how many UE's + * Unserved in this subframe. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] U32 ueCount + * @return U8 + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnGetBiIndex +( +RgSchCellCb *cell, +U32 ueCount +) +#else +PUBLIC U8 rgSCHCmnGetBiIndex(cell, ueCount) +RgSchCellCb *cell; +U32 ueCount; +#endif +{ + S16 prevVal = 0; /* To Store Intermediate Value */ + U16 newBiVal = 0; /* To store Bi Value in millisecond */ + U8 idx = 0; + U16 timeDiff = 0; + + TRC2(rgSCHCmnGetBiIndex) + + if (cell->biInfo.prevBiTime != 0) + { +#ifdef EMTC_ENABLE + if(cell->emtcEnable == TRUE) + { + timeDiff =(RGSCH_CALC_SF_DIFF_EMTC(cell->crntTime, cell->biInfo.biTime)); + } + else +#endif + { + timeDiff =(RGSCH_CALC_SF_DIFF(cell->crntTime, cell->biInfo.biTime)); + } + + prevVal = cell->biInfo.prevBiTime - timeDiff; + } + if (prevVal < 0) + { + prevVal = 0; + } + newBiVal = RG_SCH_CMN_GET_BI_VAL(prevVal,ueCount); + /* To be used next time when BI is calculated */ +#ifdef EMTC_ENABLE + if(cell->emtcEnable == TRUE) + { + RGSCHCPYTIMEINFO_EMTC(cell->crntTime, cell->biInfo.biTime) + } + else +#endif + { + RGSCHCPYTIMEINFO(cell->crntTime, cell->biInfo.biTime) + } + + /* Search the actual BI Index from table Backoff Parameters Value and + * return that Index */ + do + { + if (rgSchCmnBiTbl[idx] > newBiVal) + { + break; + } + idx++; + }while(idx < RG_SCH_CMN_NUM_BI_VAL-1); + cell->biInfo.prevBiTime = rgSchCmnBiTbl[idx]; + /* For 16 Entries in Table 7.2.1 36.321.880 - 3 reserved so total 13 Entries */ + RETVALUE(idx); /* Returning reserved value from table UE treats it has 960 ms */ +} /* rgSCHCmnGetBiIndex */ + + +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * RAR allocations. Assumption: The reuqested + * allocations are always satisfied completely. + * Hence no roll back. + * + * @details + * + * Function: rgSCHCmnDlRaRspFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * Takes care of PDCCH filling. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRaRspFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlRaRspFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + U32 rarCnt = 0; + RgSchDlRbAlloc *raRspAlloc; + RgSchDlSf *subFrm = NULLP; + RgSchRaCb *raCb; + RgSchErrInfo err; + CmLListCp *reqLst; + RgSchRaReqInfo *raReq; + Bool preamGrpA; + RgSchUlAlloc *ulAllocRef=NULLP; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 allocRapidCnt = 0; +#ifdef LTE_TDD + U32 msg3SchdIdx = 0; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 msg3Subfrm; +#endif + + TRC2(rgSCHCmnDlRaRspFnlz); + + for (rarCnt=0; rarCntraRspAlloc[rarCnt]; + /* Having likely condition first for optimization */ + if (!raRspAlloc->pdcch) + { + continue; + } + else + { + subFrm = raRspAlloc->dlSf; + reqLst = &cell->raInfo.raReqLst[raRspAlloc->raIndex]; + /* Corrected RACH handling for multiple RAPIDs per RARNTI */ + allocRapidCnt = raRspAlloc->numRapids; + while (allocRapidCnt) + { + raReq = (RgSchRaReqInfo *)(reqLst->first->node); + /* RACHO: If dedicated preamble, then allocate UL Grant + * (consequence of handover/pdcchOrder) and continue */ + if (RGSCH_IS_DEDPRM(cell, raReq->raReq.rapId)) + { + rgSCHCmnHdlHoPo(cell, &subFrm->raRsp[rarCnt].contFreeUeLst, + raReq); + cmLListDelFrm(reqLst, reqLst->first); + allocRapidCnt--; + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReq, + sizeof(RgSchRaReqInfo)); + continue; + } + /* ccpu00139815 */ + if(cell->overLoadBackOffEnab) + {/* rach Overlaod conrol is triggerd, Skipping this rach */ + cmLListDelFrm(reqLst, reqLst->first); + allocRapidCnt--; + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReq, + sizeof(RgSchRaReqInfo)); + continue; + } + /* Attempt to include each RA request into the RSP */ + /* Any failure in the procedure is considered to */ + /* affect futher allocations in the same TTI. When */ + /* a failure happens, we break out and complete */ + /* the processing for random access */ + if (rgSCHRamCreateRaCb(cell, &raCb, &err) != ROK) + { + break; + } + /* Msg3 allocation request to USM */ + if (raReq->raReq.rapId < cell->rachCfg.sizeRaPreambleGrpA) + preamGrpA = TRUE; + else + preamGrpA = FALSE; + /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/ + rgSCHCmnMsg3GrntReq(cell, raCb->tmpCrnti, preamGrpA, \ + &(raCb->msg3HqProc), &ulAllocRef, &raCb->msg3HqProcId); + if (ulAllocRef == NULLP) + { + rgSCHRamDelRaCb(cell, raCb, TRUE); + break; + } + if (raReq->raReq.cqiPres) + { + raCb->ccchCqi = raReq->raReq.cqiIdx; + } + else + { + raCb->ccchCqi = cellDl->ccchCqi; + } + raCb->rapId = raReq->raReq.rapId; + raCb->ta.pres = TRUE; + raCb->ta.val = raReq->raReq.ta; + raCb->msg3Grnt = ulAllocRef->grnt; + /* Populating the tpc value received */ + raCb->msg3Grnt.tpc = raReq->raReq.tpc; + /* PHR handling for MSG3 */ + ulAllocRef->raCb = raCb; +#ifndef LTE_TDD + /* To the crntTime, add the MIN time at which UE will + * actually send MSG3 i.e DL_DELTA+6 */ + raCb->msg3AllocTime = cell->crntTime; + RGSCH_INCR_SUB_FRAME(raCb->msg3AllocTime, RG_SCH_CMN_MIN_MSG3_RECP_INTRVL); +#else + msg3SchdIdx = (cell->crntTime.subframe+RG_SCH_CMN_DL_DELTA) % + RGSCH_NUM_SUB_FRAMES; + /*[ccpu00134666]-MOD-Modify the check to schedule the RAR in + special subframe */ + if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][msg3SchdIdx] != + RG_SCH_TDD_UL_SUBFRAME) + { + RGSCHCMNADDTOCRNTTIME(cell->crntTime,raCb->msg3AllocTime, + RG_SCH_CMN_DL_DELTA) + msg3Subfrm = rgSchTddMsg3SubfrmTbl[ulDlCfgIdx][ + raCb->msg3AllocTime.subframe]; + RGSCHCMNADDTOCRNTTIME(raCb->msg3AllocTime, raCb->msg3AllocTime, + msg3Subfrm); + } +#endif + cmLListAdd2Tail(&subFrm->raRsp[rarCnt].raRspLst, &raCb->rspLnk); + raCb->rspLnk.node = (PTR)raCb; + cmLListDelFrm(reqLst, reqLst->first); + allocRapidCnt--; + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReq, + sizeof(RgSchRaReqInfo)); + + /* SR_RACH_STATS : RAR scheduled */ + rgNumRarSched++; + + } + /* R8 Upgrade */ + /* Fill subframe data members */ + subFrm->raRsp[rarCnt].raRnti = raRspAlloc->rnti; + subFrm->raRsp[rarCnt].pdcch = raRspAlloc->pdcch; + subFrm->raRsp[rarCnt].tbSz = raRspAlloc->tbInfo[0].bytesAlloc; + /* Fill PDCCH data members */ + rgSCHCmnFillPdcch(cell, subFrm->raRsp[rarCnt].pdcch, raRspAlloc); + + /* ccpu00139815 */ + if(cell->overLoadBackOffEnab) + {/* rach Overlaod conrol is triggerd, Skipping this rach */ + subFrm->raRsp[rarCnt].backOffInd.pres = PRSNT_NODEF; + subFrm->raRsp[rarCnt].backOffInd.val = cell->overLoadBackOffval; + continue; + } + else + { + subFrm->raRsp[rarCnt].backOffInd.pres = NOTPRSNT; + } + + /*[ccpu00125212] Avoiding sending of empty RAR in case of RAR window + is short and UE is sending unauthorised preamble.*/ + reqLst = &cell->raInfo.raReqLst[raRspAlloc->raIndex]; + if ((raRspAlloc->biEstmt) && (reqLst->count)) + { + subFrm->raRsp[0].backOffInd.pres = PRSNT_NODEF; + /* Added as part of Upgrade */ + subFrm->raRsp[0].backOffInd.val = + rgSCHCmnGetBiIndex(cell, reqLst->count); + + /* SR_RACH_STATS : Back Off Inds */ + rgNumBI++; + + } + else if ((subFrm->raRsp[rarCnt].raRspLst.first == NULLP) && + (subFrm->raRsp[rarCnt].contFreeUeLst.first == NULLP)) + { + /* Return the grabbed PDCCH */ + rgSCHUtlPdcchPut(cell, &subFrm->pdcchInfo, raRspAlloc->pdcch); + subFrm->raRsp[rarCnt].pdcch = NULLP; + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnRaRspAlloc(): " + "Not even one RaReq."); + RETVOID; + } + } + RLOG_ARG3(L_DEBUG,DBG_CELLID,cell->cellId, + "RNTI:%d Scheduled RAR @ (%u,%u) ", + raRspAlloc->rnti, + cell->crntTime.sfn, + cell->crntTime.subframe); + } + RETVOID; +} + +/** + * @brief This function computes rv. + * + * @details + * + * Function: rgSCHCmnDlCalcRvForBcch + * Purpose: This function computes rv. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] Bool si + * @param[in] U16 i + * @return U8 + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnDlCalcRvForBcch +( +RgSchCellCb *cell, +Bool si, +U16 i +) +#else +PRIVATE U8 rgSCHCmnDlCalcRvForBcch(cell, si, i) +RgSchCellCb *cell; +Bool si; +U16 i; +#endif +{ + U8 k, rv; + CmLteTimingInfo frm; + TRC2(rgSCHCmnDlCalcRvForBcch); + + frm = cell->crntTime; + RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA); + + if(si) + { + k = i % 4; + } + else + { + k = (frm.sfn/2) % 4; + } + rv = RGSCH_CEIL(3*k, 2) % 4; + RETVALUE(rv); +} + +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested + * BCCH/PCCH allocations. Assumption: The reuqested + * allocations are always satisfied completely. + * Hence no roll back. + * + * @details + * + * Function: rgSCHCmnDlBcchPcchFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * Takes care of PDCCH filling. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlBcchPcchFnlz +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlBcchPcchFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchDlRbAlloc *rbAllocInfo; + RgSchDlSf *subFrm; + +#ifdef LTE_TDD + U8 nextSfIdx = (cell->crntSfIdx) % RGSCH_SF_ALLOC_SIZE; +#else +#ifdef LTEMAC_HDFDD + U8 nextSfIdx = (cell->crntSfIdx + RG_SCH_CMN_HARQ_INTERVAL) % RGSCH_NUM_SUB_FRAMES; +#else + U8 nextSfIdx = (cell->crntSfIdx) % RGSCH_NUM_SUB_FRAMES; +#endif +#endif + + /* Moving variables to available scope for optimization */ + RgSchClcDlLcCb *pcch; + RgSchClcBoRpt *bo; +#ifndef RGR_SI_SCH + RgSchClcDlLcCb *bcch; + Bool sendInd=TRUE; +#endif + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + + TRC2(rgSCHCmnDlBcchPcchFnlz); + + /* handle PCCH */ + rbAllocInfo = &allocInfo->pcchAlloc; + if (rbAllocInfo->pdcch) + { + RgInfSfAlloc *subfrmAlloc = &(cell->sfAllocArr[nextSfIdx]); + + /* Added sfIdx calculation for TDD as well */ +#ifndef LTE_TDD +#ifdef LTEMAC_HDFDD + nextSfIdx = (cell->crntSfIdx + RG_SCH_CMN_HARQ_INTERVAL) % RGSCH_NUM_SUB_FRAMES; +#else + nextSfIdx = (cell->crntSfIdx) % RGSCH_NUM_SUB_FRAMES; +#endif +#endif + subFrm = rbAllocInfo->dlSf; + pcch = rgSCHDbmGetPcch(cell); + if(pcch == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnDlBcchPcchFnlz( ): " + "No Pcch Present"); + RETVOID; + } + + /* Added Dl TB count for paging message transmission*/ +#ifdef LTE_L2_MEAS + cell->dlUlTbCnt.tbTransDlTotalCnt++; +#endif + bo = (RgSchClcBoRpt *)pcch->boLst.first->node; + cmLListDelFrm(&pcch->boLst, &bo->boLstEnt); + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&bo, sizeof(RgSchClcBoRpt)); + /* Fill subframe data members */ + subFrm->pcch.tbSize = rbAllocInfo->tbInfo[0].bytesAlloc; + subFrm->pcch.pdcch = rbAllocInfo->pdcch; + /* Fill PDCCH data members */ + rgSCHCmnFillPdcch(cell, subFrm->pcch.pdcch, rbAllocInfo); + rgSCHUtlFillRgInfCmnLcInfo(subFrm, subfrmAlloc, pcch->lcId, TRUE); + /* ccpu00132314-ADD-Update the tx power allocation info + TODO-Need to add a check for max tx power per symbol */ + subfrmAlloc->cmnLcInfo.pcchInfo.txPwrOffset = cellDl->pcchTxPwrOffset; + } + + /* handle BCCH */ + rbAllocInfo = &allocInfo->bcchAlloc; + if (rbAllocInfo->pdcch) + { + RgInfSfAlloc *subfrmAlloc = &(cell->sfAllocArr[nextSfIdx]); +#ifndef LTE_TDD +#ifdef LTEMAC_HDFDD + nextSfIdx = (cell->crntSfIdx + RG_SCH_CMN_HARQ_INTERVAL) % RGSCH_NUM_SUB_FRAMES; +#else + nextSfIdx = (cell->crntSfIdx) % RGSCH_NUM_SUB_FRAMES; +#endif +#endif + subFrm = rbAllocInfo->dlSf; + + /* Fill subframe data members */ + subFrm->bcch.tbSize = rbAllocInfo->tbInfo[0].bytesAlloc; + subFrm->bcch.pdcch = rbAllocInfo->pdcch; + /* Fill PDCCH data members */ + rgSCHCmnFillPdcch(cell, subFrm->bcch.pdcch, rbAllocInfo); + + if(rbAllocInfo->schdFirst) + { +#ifndef RGR_SI_SCH + bcch = rgSCHDbmGetFirstBcchOnDlsch(cell); + bo = (RgSchClcBoRpt *)bcch->boLst.first->node; +#else + /*Copy the SIB1 msg buff into interface buffer */ + SCpyMsgMsg(cell->siCb.crntSiInfo.sib1Info.sib1, + rgSchCb[cell->instIdx].rgSchInit.region, + rgSchCb[cell->instIdx].rgSchInit.pool, + &subfrmAlloc->cmnLcInfo.bcchInfo.pdu); +#endif/*RGR_SI_SCH*/ + subFrm->bcch.pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.rv = + rgSCHCmnDlCalcRvForBcch(cell, FALSE, 0); + } + else + { + U16 i; +#ifdef RGR_SI_SCH + Buffer *pdu; + + i = cell->siCb.siCtx.i; + /*Decrement the retransmission count */ + cell->siCb.siCtx.retxCntRem--; + + /*Copy the SI msg buff into interface buffer */ + if(cell->siCb.siCtx.warningSiFlag == FALSE) + { + SCpyMsgMsg(cell->siCb.siArray[cell->siCb.siCtx.siId-1].si, + rgSchCb[cell->instIdx].rgSchInit.region, + rgSchCb[cell->instIdx].rgSchInit.pool, + &subfrmAlloc->cmnLcInfo.bcchInfo.pdu); + } + else + { + pdu = rgSCHUtlGetWarningSiPdu(cell); + RGSCH_NULL_CHECK(cell->instIdx, pdu); + SCpyMsgMsg(pdu, + rgSchCb[cell->instIdx].rgSchInit.region, + rgSchCb[cell->instIdx].rgSchInit.pool, + &subfrmAlloc->cmnLcInfo.bcchInfo.pdu); + if(cell->siCb.siCtx.retxCntRem == 0) + { + rgSCHUtlFreeWarningSiPdu(cell); + cell->siCb.siCtx.warningSiFlag = FALSE; + + } + } +#else + bcch = rgSCHDbmGetSecondBcchOnDlsch(cell); + bo = (RgSchClcBoRpt *)bcch->boLst.first->node; + bo->retxCnt--; + if(bo->retxCnt != cell->siCfg.retxCnt-1) + { + sendInd=FALSE; + } + i = bo->i; +#endif/*RGR_SI_SCH*/ + subFrm->bcch.pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.rv = + rgSCHCmnDlCalcRvForBcch(cell, TRUE, i); + } + + /* Added Dl TB count for SIB1 and SI messages transmission. + * This counter will be incremented only for the first transmission + * (with RV 0) of these messages*/ +#ifdef LTE_L2_MEAS + if(subFrm->bcch.pdcch->dci.u.format1aInfo.t.pdschInfo.allocInfo.rv == 0) + { + cell->dlUlTbCnt.tbTransDlTotalCnt++; + } +#endif +#ifndef RGR_SI_SCH + if(bo->retxCnt == 0) + { + cmLListDelFrm(&bcch->boLst, &bo->boLstEnt); + /* ccpu00117052 - MOD - Passing double pointer + for proper NULLP assignment*/ + rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&bo, sizeof(RgSchClcBoRpt)); + } + rgSCHUtlFillRgInfCmnLcInfo(subFrm, subfrmAlloc, bcch->lcId, sendInd); +#else + /*Fill the interface info */ + rgSCHUtlFillRgInfCmnLcInfo(subFrm, subfrmAlloc, NULLD, NULLD); + + /* ccpu00132314-ADD-Update the tx power allocation info + TODO-Need to add a check for max tx power per symbol */ + subfrmAlloc->cmnLcInfo.bcchInfo.txPwrOffset = cellDl->bcchTxPwrOffset; + + /*mBuf has been already copied above */ +#endif/*RGR_SI_SCH*/ + } + + RETVOID; +} + + +#if RG_UNUSED +/** + * @brief + * + * @details + * + * Function: rgSCHCmnUlSetAllUnSched + * Purpose: + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnUlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlSetAllUnSched +( +RgSchCmnUlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnUlSetAllUnSched(allocInfo) +RgSchCmnUlRbAllocInfo *allocInfo; +#endif +{ + CmLList *node; + + TRC2(rgSCHCmnUlSetAllUnSched); + + node = allocInfo->contResLst.first; + while (node) + { + rgSCHCmnUlMov2NonSchdCntResLst(allocInfo, (RgSchUeCb *)node->node); + node = allocInfo->contResLst.first; + } + + node = allocInfo->retxUeLst.first; + while (node) + { + rgSCHCmnUlMov2NonSchdRetxUeLst(allocInfo, (RgSchUeCb *)node->node); + node = allocInfo->retxUeLst.first; + } + + node = allocInfo->ueLst.first; + while (node) + { + rgSCHCmnUlMov2NonSchdUeLst(allocInfo, (RgSchUeCb *)node->node); + node = allocInfo->ueLst.first; + } + + RETVOID; +} +#endif + +/** + * @brief + * + * @details + * + * Function: rgSCHCmnUlAdd2CntResLst + * Purpose: + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnUlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAdd2CntResLst +( +RgSchCmnUlRbAllocInfo *allocInfo, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlAdd2CntResLst(allocInfo, ue) +RgSchCmnUlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +#endif +{ + RgSchCmnUeUlAlloc *ulAllocInfo = &((RG_SCH_CMN_GET_UL_UE(ue,ue->cell))->alloc); + TRC2(rgSCHCmnUlAdd2CntResLst); + cmLListAdd2Tail(&allocInfo->contResLst, &ulAllocInfo->reqLnk); + ulAllocInfo->reqLnk.node = (PTR)ue; + RETVOID; +} + +/** + * @brief + * + * @details + * + * Function: rgSCHCmnUlAdd2UeLst + * Purpose: + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnUlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlAdd2UeLst +( +RgSchCellCb *cell, +RgSchCmnUlRbAllocInfo *allocInfo, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlAdd2UeLst(cell, allocInfo, ue) +RgSchCellCb *cell; +RgSchCmnUlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +#endif +{ + RgSchCmnUeUlAlloc *ulAllocInfo = &((RG_SCH_CMN_GET_UL_UE(ue,cell))->alloc); + TRC2(rgSCHCmnUlAdd2UeLst); + if (ulAllocInfo->reqLnk.node == NULLP) + { + cmLListAdd2Tail(&allocInfo->ueLst, &ulAllocInfo->reqLnk); + ulAllocInfo->reqLnk.node = (PTR)ue; + } + RETVOID; +} + +/** + * @brief + * + * @details + * + * Function: rgSCHCmnAllocUlRb + * Purpose: To do RB allocations for uplink + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnUlRbAllocInfo *allocInfo + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnAllocUlRb +( +RgSchCellCb *cell, +RgSchCmnUlRbAllocInfo *allocInfo +) +#else +PUBLIC Void rgSCHCmnAllocUlRb(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnUlRbAllocInfo *allocInfo; +#endif +{ + RgSchUlSf *sf = allocInfo->sf; + TRC2(rgSCHCmnAllocUlRb); + + /* Schedule for new transmissions */ + rgSCHCmnUlRbAllocForLst(cell, sf, allocInfo->ueLst.count, + &allocInfo->ueLst, &allocInfo->schdUeLst, + &allocInfo->nonSchdUeLst, (Bool)TRUE); + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnUlRbAllocForLst + * + * Desc : Allocate for a list in cmn rb alloc information passed + * in a subframe. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlRbAllocForLst +( +RgSchCellCb *cell, +RgSchUlSf *sf, +U32 count, +CmLListCp *reqLst, +CmLListCp *schdLst, +CmLListCp *nonSchdLst, +Bool isNewTx +) +#else +PRIVATE Void rgSCHCmnUlRbAllocForLst(cell, sf, count, reqLst, schdLst, + nonSchdLst, isNewTx) +RgSchCellCb *cell; +RgSchUlSf *sf; +U32 count; +CmLListCp *reqLst; +CmLListCp *schdLst; +CmLListCp *nonSchdLst; +Bool isNewTx; +#endif +{ + CmLList *lnk; + RgSchUlHole *hole; +#ifdef LTE_L2_MEAS +#ifdef LTE_TDD + U8 k; + CmLteTimingInfo timeInfo; +#endif +#endif + TRC2(rgSCHCmnUlRbAllocForLst); + + if(schdLst->count == 0) + { + cmLListInit(schdLst); + } + + cmLListInit(nonSchdLst); +#ifdef LTE_L2_MEAS + if(isNewTx == TRUE) + { + cell->sfAllocArr[cell->crntSfIdx].ulUeInfo.numUes = (U8) count; +#ifdef LTE_TDD + RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, timeInfo, TFU_ULCNTRL_DLDELTA); + k = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][timeInfo.subframe]; + RG_SCH_ADD_TO_CRNT_TIME(timeInfo, + cell->sfAllocArr[cell->crntSfIdx].ulUeInfo.timingInfo, k); +#else + RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime,cell->sfAllocArr[cell->crntSfIdx].ulUeInfo.timingInfo, + (TFU_ULCNTRL_DLDELTA + RGSCH_PDCCH_PUSCH_DELTA)); +#endif + } +#endif + + for (lnk = reqLst->first; count; lnk = lnk->next, --count) + { + RgSchUeCb *ue = (RgSchUeCb *)lnk->node; + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell); + S16 ret; + U8 maxRb; + + + if ((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP) + { + break; + } + + ueUl->subbandShare = ueUl->subbandRequired; + if(isNewTx == TRUE) + { + maxRb = RGSCH_MIN((ueUl->subbandRequired * MAX_5GTF_VRBG_SIZE), ue->ue5gtfCb.maxPrb); + } + ret = rgSCHCmnUlRbAllocForUe(cell, sf, ue, maxRb, hole); + if (ret == ROK) + { + rgSCHCmnUlRbAllocAddUeToLst(cell, ue, schdLst); + rgSCHCmnUlUeFillAllocInfo(cell, ue); + } + else + { + gUl5gtfRbAllocFail++; +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.ul5gtfRbAllocFail++; +#endif + rgSCHCmnUlRbAllocAddUeToLst(cell, ue, nonSchdLst); + ue->isMsg4PdcchWithCrnti = FALSE; + ue->isSrGrant = FALSE; + } +#ifdef LTE_L2_MEAS + if(isNewTx == TRUE) + { + cell->sfAllocArr[cell->crntSfIdx].ulUeInfo. + ulAllocInfo[count - 1].rnti = ue->ueId; + cell->sfAllocArr[cell->crntSfIdx].ulUeInfo. + ulAllocInfo[count - 1].numPrb = ue->ul.nPrb; + } +#endif + ueUl->subbandShare = 0; /* This reset will take care of + * all scheduler types */ + } + for (; count; lnk = lnk->next, --count) + { + RgSchUeCb *ue = (RgSchUeCb *)lnk->node; + rgSCHCmnUlRbAllocAddUeToLst(cell, ue, nonSchdLst); + ue->isMsg4PdcchWithCrnti = FALSE; + } + RETVOID; +} + +#ifdef TFU_UPGRADE +/*********************************************************** + * + * Func : rgSCHCmnUlMdfyGrntForCqi + * + * Desc : Modify UL Grant to consider presence of + * CQI along with PUSCH Data. + * + * Ret : + * + * Notes: + * - Scale down iTbs based on betaOffset and + * size of Acqi Size. + * - Optionally attempt to increase numSb by 1 + * if input payload size does not fit in due + * to reduced tbSz as a result of iTbsNew. + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlMdfyGrntForCqi +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 maxRb, +U32 *numSb, +U8 *iTbs, +U32 hqSz, +U32 stepDownItbs, +U32 effTgt +) +#else +PRIVATE S16 rgSCHCmnUlMdfyGrntForCqi(cell, ue, maxRb, numSb, iTbs, hqSz, stepDownItbs, effTgt) +RgSchCellCb *cell; +RgSchUeCb *ue; +U32 maxRb; +U32 *numSb; +U8 *iTbs; +U32 hqSz; +U32 stepDownItbs; +U32 effTgt; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(ue->cell); + U32 nPrb; + U32 totREs; + U32 cqiRiREs; + U32 hqREs; + U32 remREsForPusch; + U32 bitsPerRe; + U32 tbSz; + U32 betaOffVal = ue->ul.betaOffstVal; + U32 cqiRiRptSz = ue->ul.cqiRiSz; + U32 betaOffHqVal = rgSchCmnBetaHqOffstTbl[ue->ul.betaHqOffst]; + U32 resNumSb = *numSb; + U32 puschEff = 1000; + U8 modOdr; + U8 iMcs; + Bool mdfyiTbsFlg = FALSE; + U8 resiTbs = *iTbs; + + TRC2(rgSCHCmnUlMdfyGrntForCqi) + + + do + { + iMcs = rgSCHCmnUlGetIMcsFrmITbs(resiTbs, RG_SCH_CMN_GET_UE_CTGY(ue)); + RG_SCH_UL_MCS_TO_MODODR(iMcs, modOdr); + if (RG_SCH_CMN_GET_UE_CTGY(ue) != CM_LTE_UE_CAT_5) + { + modOdr = RGSCH_MIN(RGSCH_QM_QPSK, modOdr); + } + else + { + modOdr = RGSCH_MIN(RGSCH_QM_64QAM, modOdr); + } + nPrb = resNumSb * cellUl->sbSize; + /* Restricting the minumum iTbs requried to modify to 10 */ + if ((nPrb >= maxRb) && (resiTbs <= 10)) + { + /* Could not accomodate ACQI */ + RETVALUE(RFAILED); + } + totREs = nPrb * RG_SCH_CMN_UL_NUM_RE_PER_RB(cellUl); + tbSz = rgTbSzTbl[0][resiTbs][nPrb-1]; + /* totalREs/tbSz = num of bits perRE. */ + cqiRiREs = (totREs * betaOffVal * cqiRiRptSz)/(1000 * tbSz); /* betaOffVal is represented + as parts per 1000 */ + hqREs = (totREs * betaOffHqVal * hqSz)/(1000 * tbSz); + if ((cqiRiREs + hqREs) < totREs) + { + remREsForPusch = totREs - cqiRiREs - hqREs; + bitsPerRe = (tbSz * 1000)/remREsForPusch; /* Multiplying by 1000 for Interger Oper */ + puschEff = bitsPerRe/modOdr; + } + if (puschEff < effTgt) + { + /* ensure resultant efficiency for PUSCH Data is within 0.93*/ + break; + } + else + { + /* Alternate between increasing SB or decreasing iTbs until eff is met */ + if (mdfyiTbsFlg == FALSE) + { + if (nPrb < maxRb) + { + resNumSb = resNumSb + 1; + } + mdfyiTbsFlg = TRUE; + } + else + { + if (resiTbs > 10) + { + resiTbs-= stepDownItbs; + } + mdfyiTbsFlg = FALSE; + } + } + }while (1); /* Loop breaks if efficency is met + or returns RFAILED if not able to meet the efficiency */ + + *numSb = resNumSb; + *iTbs = resiTbs; + + RETVALUE(ROK); +} +#endif +/*********************************************************** + * + * Func : rgSCHCmnUlRbAllocForUe + * + * Desc : Do uplink RB allocation for an UE. + * + * Ret : + * + * Notes: Note that as of now, for retx, maxRb + * is not considered. Alternatives, such + * as dropping retx if it crosses maxRb + * could be considered. + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlRbAllocForUe +( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUeCb *ue, +U8 maxRb, +RgSchUlHole *hole +) +#else +PRIVATE S16 rgSCHCmnUlRbAllocForUe(cell, sf, ue, maxRb, hole) +RgSchCellCb *cell; +RgSchUlSf *sf; +RgSchUeCb *ue; +U8 maxRb; +RgSchUlHole *hole; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell); + RgSchUlAlloc *alloc = NULLP; + U32 nPrb = 0; + U8 numVrbg; + U8 iMcs; + U8 iMcsCrnt; +#ifndef RG_5GTF + RgSchUlHqProcCb *proc = &ueUl->hqEnt.hqProcCb[cellUl->schdHqProcIdx]; +#else + RgSchUlHqProcCb *proc = NULLP; +#endif + RgSchPdcch *pdcch; + U32 reqVrbg; + U8 numVrbgTemp; +#ifdef RG_5GTF + TfuDciFormat dciFrmt; + U8 numLyr; +#endif + + TRC2(rgSCHCmnUlRbAllocForUe); +#ifdef RG_5GTF + rgSCHUhmGetAvlHqProc(cell, ue, &proc); + if (proc == NULLP) + { + //printf("UE [%d] HQ Proc unavailable\n", ue->ueId); + RETVALUE(RFAILED); + } +#endif + + if (ue->ue5gtfCb.rank == 2) + { + dciFrmt = TFU_DCI_FORMAT_A2; + numLyr = 2; + } + else + { + dciFrmt = TFU_DCI_FORMAT_A1; + numLyr = 1; + } + /* 5gtf TODO : To pass dci frmt to this function */ + pdcch = rgSCHCmnPdcchAllocCrntSf(cell, ue); + if(pdcch == NULLP) + { + RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId, + "rgSCHCmnUlRbAllocForUe(): Could not get PDCCH for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + gUl5gtfPdcchSchd++; +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.ul5gtfPdcchSchd++; +#endif + + //TODO_SID using configured prb as of now + nPrb = ue->ue5gtfCb.maxPrb; + reqVrbg = nPrb/MAX_5GTF_VRBG_SIZE; + iMcs = ue->ue5gtfCb.mcs; //gSCHCmnUlGetIMcsFrmITbs(iTbs,ueCtg); + iMcsCrnt = iMcs; + numVrbg = reqVrbg; + + if((sf->sfBeamInfo[ue->ue5gtfCb.BeamId].vrbgStart > MAX_5GTF_VRBG) + || (sf->sfBeamInfo[ue->ue5gtfCb.BeamId].totVrbgAllocated > MAX_5GTF_VRBG)) + { + printf("5GTF_ERROR vrbg > 25 valstart = %d valalloc %d\n", sf->sfBeamInfo[ue->ue5gtfCb.BeamId].vrbgStart + , sf->sfBeamInfo[ue->ue5gtfCb.BeamId].totVrbgAllocated); + int *p=NULLP; + *p = 10; + } + + /*TODO_SID: Workaround for alloc. Currently alloc is ulsf based. To handle multiple beams, we need a different + design. Now alloc are formed based on MAX_5GTF_UE_SCH macro. */ + numVrbgTemp = MAX_5GTF_VRBG/MAX_5GTF_UE_SCH; + if(numVrbg) + { + alloc = rgSCHCmnUlSbAlloc(sf, numVrbgTemp,\ + hole); + } + if (alloc == NULLP) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnUlRbAllocForUe(): Could not get UlAlloc %d CRNTI:%d",numVrbg,ue->ueId); + rgSCHCmnPdcchRlsCrntSf(cell, pdcch); + RETVALUE(RFAILED); + } + gUl5gtfAllocAllocated++; +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.ul5gtfAllocAllocated++; +#endif + alloc->grnt.vrbgStart = sf->sfBeamInfo[ue->ue5gtfCb.BeamId].vrbgStart; + alloc->grnt.numVrbg = numVrbg; + alloc->grnt.numLyr = numLyr; + alloc->grnt.dciFrmt = dciFrmt; + + sf->sfBeamInfo[ue->ue5gtfCb.BeamId].vrbgStart += numVrbg; + sf->sfBeamInfo[ue->ue5gtfCb.BeamId].totVrbgAllocated += numVrbg; + + //rgSCHCmnUlAllocFillRbInfo(cell, sf, alloc); +#ifdef LTE_L2_MEAS + sf->totPrb += alloc->grnt.numRb; + ue->ul.nPrb = alloc->grnt.numRb; +#endif + if (ue->csgMmbrSta != TRUE) + { + cellUl->ncsgPrbCnt += alloc->grnt.numRb; + } + cellUl->totPrbCnt += (alloc->grnt.numVrbg * MAX_5GTF_VRBG_SIZE); + alloc->pdcch = pdcch; + alloc->grnt.iMcs = iMcs; + alloc->grnt.iMcsCrnt = iMcsCrnt; + alloc->grnt.hop = 0; + /* Initial Num RBs support for UCI on PUSCH */ +#ifdef TFU_UPGRADE + ue->initNumRbs = (alloc->grnt.numVrbg * MAX_5GTF_VRBG_SIZE); +#endif + alloc->forMsg3 = FALSE; + //RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgTb5gtfSzTbl[0], (iTbs)); + + //ueUl->alloc.allocdBytes = rgTbSzTbl[0][iTbs][alloc->grnt.numRb-1] / 8; + /* TODO_SID Allocating based on configured MCS as of now. + Currently for format A2. When doing multi grp per tti, need to update this. */ + ueUl->alloc.allocdBytes = (rgSch5gtfTbSzTbl[iMcs]/8) * ue->ue5gtfCb.rank; + + alloc->grnt.datSz = ueUl->alloc.allocdBytes; + //TODO_SID Need to check mod order. + RG_SCH_CMN_TBS_TO_MODODR(iMcs, alloc->grnt.modOdr); + //alloc->grnt.modOdr = 6; + alloc->grnt.isRtx = FALSE; + + alloc->grnt.rbAssign = rgSCHCmnCalcRiv(MAX_5GTF_VRBG, alloc->grnt.vrbgStart, alloc->grnt.numVrbg); + alloc->grnt.SCID = 0; + alloc->grnt.xPUSCHRange = MAX_5GTF_XPUSCH_RANGE; + alloc->grnt.PMI = 0; + alloc->grnt.uciOnxPUSCH = 0; + alloc->grnt.hqProcId = proc->procId; + + alloc->hqProc = proc; + alloc->hqProc->ulSfIdx = cellUl->schdIdx; + alloc->ue = ue; + /*commenting to retain the rnti used for transmission SPS/c-rnti */ + alloc->rnti = ue->ueId; + ueUl->alloc.alloc = alloc; + /*rntiwari-Adding the debug for generating the graph.*/ + /* No grant attr recorded now */ + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlRbAllocAddUeToLst + * + * Desc : Add UE to list (scheduled/non-scheduled list) + * for UL RB allocation information. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlRbAllocAddUeToLst +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLListCp *lst +) +#else +PUBLIC Void rgSCHCmnUlRbAllocAddUeToLst(cell, ue, lst) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLListCp *lst; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + TRC2(rgSCHCmnUlRbAllocAddUeToLst); + UNUSED(cell); + + gUl5gtfUeRbAllocDone++; +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.ul5gtfUeRbAllocDone++; +#endif + cmLListAdd2Tail(lst, &ueUl->alloc.schdLstLnk); + ueUl->alloc.schdLstLnk.node = (PTR)ue; +} + + +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * + * @details + * + * Function: rgSCHCmnUlAllocFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnUlRbAllocInfo *allocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlAllocFnlz +( +RgSchCellCb *cell, +RgSchCmnUlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnUlAllocFnlz(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnUlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnUlAllocFnlz); + + /* call scheduler specific Finalization */ + cellSch->apisUl->rgSCHUlAllocFnlz(cell, allocInfo); + + RETVOID; +} + +/** + * @brief This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * + * @details + * + * Function: rgSCHCmnDlAllocFnlz + * Purpose: This function Processes the Final Allocations + * made by the RB Allocator against the requested. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlAllocFnlz +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnDlAllocFnlz(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlRbAllocInfo *allocInfo = &cellSch->allocInfo; + + TRC2(rgSCHCmnDlAllocFnlz); + + rgSCHCmnDlCcchRetxFnlz(cell, allocInfo); + rgSCHCmnDlCcchTxFnlz(cell, allocInfo); +#ifdef RGR_V1 + /* Added below functions for handling CCCH SDU transmission received + * after + * * guard timer expiry*/ + rgSCHCmnDlCcchSduRetxFnlz(cell, allocInfo); + rgSCHCmnDlCcchSduTxFnlz(cell, allocInfo); +#endif + rgSCHCmnDlRaRspFnlz(cell, allocInfo); + /* call scheduler specific Finalization */ + cellSch->apisDl->rgSCHDlAllocFnlz(cell, allocInfo); + + /* Stack Crash problem for TRACE5 Changes. Added the return below */ + RETVOID; + +} + +#ifdef RG_UNUSED +/** + * @brief Update an uplink subframe. + * + * @details + * + * Function : rgSCHCmnUlUpdSf + * + * For each allocation + * - if no more tx needed + * - Release allocation + * - else + * - Perform retransmission + * + * @param[in] RgSchUlSf *sf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlUpdSf +( +RgSchCellCb *cell, +RgSchCmnUlRbAllocInfo *allocInfo, +RgSchUlSf *sf +) +#else +PRIVATE Void rgSCHCmnUlUpdSf(cell, allocInfo, sf) +RgSchCellCb *cell; +RgSchCmnUlRbAllocInfo *allocInfo; +RgSchUlSf *sf; +#endif +{ + CmLList *lnk; + TRC2(rgSCHCmnUlUpdSf); + + while ((lnk = sf->allocs.first)) + { + RgSchUlAlloc *alloc = (RgSchUlAlloc *)lnk->node; + lnk = lnk->next; + + if ((alloc->hqProc->rcvdCrcInd) || (alloc->hqProc->remTx == 0)) + { + } + else + { + /* If need to handle all retx together, run another loop separately */ + rgSCHCmnUlHndlAllocRetx(cell, allocInfo, sf, alloc); + } + rgSCHCmnUlRlsUlAlloc(cell, sf, alloc); + } + + /* By this time, all allocs would have been cleared and + * SF is reset to be made ready for new allocations. */ + rgSCHCmnUlSfReset(cell, sf); + /* In case there are timing problems due to msg3 + * allocations being done in advance, (which will + * probably happen with the current FDD code that + * handles 8 subframes) one solution + * could be to hold the (recent) msg3 allocs in a separate + * list, and then possibly add that to the actual + * list later. So at this time while allocations are + * traversed, the recent msg3 ones are not seen. Anytime after + * this (a good time is when the usual allocations + * are made), msg3 allocations could be transferred to the + * normal list. Not doing this now as it is assumed + * that incorporation of TDD shall take care of this. + */ + + + RETVOID; +} + +/** + * @brief Handle uplink allocation for retransmission. + * + * @details + * + * Function : rgSCHCmnUlHndlAllocRetx + * + * Processing Steps: + * - Add to queue for retx. + * - Do not release here, release happends as part + * of the loop that calls this function. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnUlRbAllocInfo *allocInfo + * @param[in] RgSchUlSf *sf + * @param[in] RgSchUlAlloc *alloc + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlHndlAllocRetx +( +RgSchCellCb *cell, +RgSchCmnUlRbAllocInfo *allocInfo, +RgSchUlSf *sf, +RgSchUlAlloc *alloc +) +#else +PRIVATE Void rgSCHCmnUlHndlAllocRetx(cell, allocInfo, sf, alloc) +RgSchCellCb *cell; +RgSchCmnUlRbAllocInfo *allocInfo; +RgSchUlSf *sf; +RgSchUlAlloc *alloc; +#endif +{ + U32 bytes; + RgSchCmnUlUe *ueUl; + TRC2(rgSCHCmnUlHndlAllocRetx); + bytes = \ + rgTbSzTbl[0][rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs)]\ + [alloc->grnt.numRb-1]/8; + if (!alloc->forMsg3) + { + ueUl = RG_SCH_CMN_GET_UL_UE(alloc->ue); + ueUl->alloc.reqBytes = bytes; + rgSCHUhmRetx(alloc->hqProc); + rgSCHCmnUlAdd2RetxUeLst(allocInfo, alloc->ue); + } + else + { + /* RACHO msg3 retx handling. Part of RACH procedure changes. */ + retxAlloc = rgSCHCmnUlGetUlAlloc(cell, sf, alloc->numSb); + if (retxAlloc == NULLP) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnUlRbAllocForUe():Could not get UlAlloc for msg3Retx RNTI:%d", + alloc->rnti); + RETVOID; + } + retxAlloc->grnt.iMcs = alloc->grnt.iMcs; + retxAlloc->grnt.iMcsCrnt = rgSchCmnUlRvIdxToIMcsTbl\ + [alloc->hqProc->rvIdx]; + retxAlloc->grnt.nDmrs = 0; + retxAlloc->grnt.hop = 0; + retxAlloc->grnt.delayBit = 0; + retxAlloc->rnti = alloc->rnti; + retxAlloc->ue = NULLP; + retxAlloc->pdcch = FALSE; + retxAlloc->forMsg3 = TRUE; + retxAlloc->raCb = alloc->raCb; + retxAlloc->hqProc = alloc->hqProc; + rgSCHUhmRetx(retxAlloc->hqProc); + } + RETVOID; +} +#endif + +/** + * @brief Uplink Scheduling Handler. + * + * @details + * + * Function: rgSCHCmnUlAlloc + * Purpose: This function Handles Uplink Scheduling. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +/* ccpu00132653- The definition of this function made common for TDD and FDD*/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlAlloc +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnUlAlloc(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchCmnUlRbAllocInfo allocInfo; + RgSchCmnUlRbAllocInfo *allocInfoRef = &allocInfo; +#ifdef RG_5GTF + U8 idx; + +#endif + + TRC2(rgSCHCmnUlAlloc); + + /* Initializing RgSchCmnUlRbAllocInfo structure */ + rgSCHCmnInitUlRbAllocInfo(allocInfoRef); + + /* Get Uplink Subframe */ + allocInfoRef->sf = &cellUl->ulSfArr[cellUl->schdIdx]; +#ifdef LTE_L2_MEAS + /* initializing the UL PRB count */ + allocInfoRef->sf->totPrb = 0; +#endif + +#ifdef LTEMAC_SPS + rgSCHCmnSpsUlTti(cell, allocInfoRef); +#endif + + if(*allocInfoRef->sf->allocCountRef == 0) + { + RgSchUlHole *hole; + + if ((hole = rgSCHUtlUlHoleFirst(allocInfoRef->sf)) != NULLP) + { + /* Sanity check of holeDb */ + if (allocInfoRef->sf->holeDb->count == 1 && hole->start == 0) + { + hole->num = cell->dynCfiCb.bwInfo[cellDl->currCfi].numSb; + /* Re-Initialize available subbands because of CFI change*/ + allocInfoRef->sf->availSubbands = cell->dynCfiCb.\ + bwInfo[cellDl->currCfi].numSb; + /*Currently initializing 5gtf ulsf specific initialization here. + need to do at proper place */ +#ifdef RG_5GTF + allocInfoRef->sf->numGrpPerTti = cell->cell5gtfCb.ueGrpPerTti; + allocInfoRef->sf->numUePerGrp = cell->cell5gtfCb.uePerGrpPerTti; + for(idx = 0; idx < MAX_5GTF_BEAMS; idx++) + { + allocInfoRef->sf->sfBeamInfo[idx].totVrbgAllocated = 0; + allocInfoRef->sf->sfBeamInfo[idx].totVrbgRequired = 0; + allocInfoRef->sf->sfBeamInfo[idx].vrbgStart = 0; + } +#endif + } + else + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "Error! holeDb sanity check failed"); + } + } + } + + /* Fix: Adaptive re-transmissions prioritised over other transmissions */ + /* perform adaptive retransmissions */ + rgSCHCmnUlSfReTxAllocs(cell, allocInfoRef->sf); + + g5gtfTtiCnt++; + + /* Fix: syed Adaptive Msg3 Retx crash. Release all + Harq processes for which adap Retx failed, to avoid + blocking. This step should be done before New TX + scheduling to make hqProc available. Right now we + dont check if proc is in adap Retx list for considering + it to be available. But now with this release that + functionality would be correct. */ +#ifndef RG_5GTF + rgSCHCmnUlSfRlsRetxProcs(cell, allocInfoRef->sf); +#endif + + /* Specific UL scheduler to perform UE scheduling */ + cellSch->apisUl->rgSCHUlSched(cell, allocInfoRef); + + /* Call UL RB allocator module */ + rgSCHCmnAllocUlRb(cell, allocInfoRef); + + /* Do group power control for PUSCH */ + rgSCHCmnGrpPwrCntrlPusch(cell, allocInfoRef->sf); + + cell->sc.apis->rgSCHDrxStrtInActvTmrInUl(cell); + + rgSCHCmnUlAllocFnlz(cell, allocInfoRef); + if(5000 == g5gtfTtiCnt) + { + ul5gtfsidDlAlreadyMarkUl = 0; + ul5gtfsidDlSchdPass = 0; + ul5gtfsidUlMarkUl = 0; + ul5gtfTotSchdCnt = 0; + g5gtfTtiCnt = 0; + } + + RETVOID; +} + +/** + * @brief send Subframe Allocations. + * + * @details + * + * Function: rgSCHCmnSndCnsldtInfo + * Purpose: Send the scheduled + * allocations to MAC for StaInd generation to Higher layers and + * for MUXing. PST's RgInfSfAlloc to MAC instance. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnSndCnsldtInfo +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnSndCnsldtInfo(cell) +RgSchCellCb *cell; +#endif +{ + RgInfSfAlloc *subfrmAlloc; + Pst pst; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnSndCnsldtInfo); + + subfrmAlloc = &(cell->sfAllocArr[cell->crntSfIdx]); + + /* Send the allocations to MAC for MUXing */ + rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst); + subfrmAlloc->cellId = cell->cellId; + /* Populate the List of UEs needing PDB-based Flow control */ + cellSch->apisDl->rgSCHDlFillFlwCtrlInfo(cell, subfrmAlloc); +#ifdef LTE_L2_MEAS + if((subfrmAlloc->rarInfo.numRaRntis) || +#ifdef EMTC_ENABLE + (subfrmAlloc->emtcInfo.rarInfo.numRaRntis) || + (subfrmAlloc->emtcInfo.cmnLcInfo.bitMask) || + (subfrmAlloc->emtcInfo.ueInfo.numUes) || +#endif + (subfrmAlloc->ueInfo.numUes) || + (subfrmAlloc->cmnLcInfo.bitMask) || + (subfrmAlloc->ulUeInfo.numUes) || + (subfrmAlloc->flowCntrlInfo.numUes)) +#else + if((subfrmAlloc->rarInfo.numRaRntis) || +#ifdef EMTC_ENABLE + (subfrmAlloc->emtcInfo.rarInfo.numRaRntis) || + (subfrmAlloc->emtcInfo.cmnLcInfo.bitMask) || + (subfrmAlloc->emtcInfo.ueInfo.numUes) || +#endif + (subfrmAlloc->ueInfo.numUes) || + (subfrmAlloc->cmnLcInfo.bitMask) || + (subfrmAlloc->flowCntrlInfo.numUes)) +#endif + { + RgSchMacSfAlloc(&pst, subfrmAlloc); + } +#ifndef LTE_TDD + cell->crntSfIdx = (cell->crntSfIdx + 1) % RGSCH_NUM_SUB_FRAMES; +#else + cell->crntSfIdx = (cell->crntSfIdx + 1) % RGSCH_SF_ALLOC_SIZE; +#endif + + RETVOID; +} +/** + * @brief Consolidate Subframe Allocations. + * + * @details + * + * Function: rgSCHCmnCnsldtSfAlloc + * Purpose: Consolidate Subframe Allocations. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnCnsldtSfAlloc +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnCnsldtSfAlloc(cell) +RgSchCellCb *cell; +#endif +{ + RgInfSfAlloc *subfrmAlloc; + CmLteTimingInfo frm; + RgSchDlSf *dlSf; + CmLListCp dlDrxInactvTmrLst; + CmLListCp dlInActvLst; + CmLListCp ulInActvLst; + RgSchCmnCell *cellSch = NULLP; + + TRC2(rgSCHCmnCnsldtSfAlloc); + + cmLListInit(&dlDrxInactvTmrLst); + cmLListInit(&dlInActvLst); + cmLListInit(&ulInActvLst); + + subfrmAlloc = &(cell->sfAllocArr[cell->crntSfIdx]); + + /* Get Downlink Subframe */ + frm = cell->crntTime; + RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA); + dlSf = rgSCHUtlSubFrmGet(cell, frm); + + /* Fill the allocation Info */ + rgSCHUtlFillRgInfRarInfo(dlSf, subfrmAlloc, cell); + + /* CA dev Start */ + rgSCHUtlFillRgInfUeInfo(dlSf, cell, &dlDrxInactvTmrLst, + &dlInActvLst, &ulInActvLst); +#ifdef RG_PFS_STATS + cell->totalPrb += dlSf->bwAssigned; +#endif + /* Mark the following Ues inactive for UL*/ + cellSch = RG_SCH_CMN_GET_CELL(cell); + + /* Calling Scheduler specific function with DRX inactive UE list*/ + cellSch->apisUl->rgSCHUlInactvtUes(cell, &ulInActvLst); + cellSch->apisDl->rgSCHDlInactvtUes(cell, &dlInActvLst); + + /* CA dev End */ + /*re/start DRX inactivity timer for the UEs*/ + (Void)rgSCHDrxStrtInActvTmr(cell,&dlDrxInactvTmrLst,RG_SCH_DRX_DL); + + RETVOID; +} + +/** + * @brief Initialize the DL Allocation Information Structure. + * + * @details + * + * Function: rgSCHCmnInitDlRbAllocInfo + * Purpose: Initialize the DL Allocation Information Structure. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnInitDlRbAllocInfo +( +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnInitDlRbAllocInfo(allocInfo) +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + TRC2(rgSCHCmnInitDlRbAllocInfo); + cmMemset((U8 *)&allocInfo->pcchAlloc, (U8)0, sizeof(RgSchDlRbAlloc)); + cmMemset((U8 *)&allocInfo->bcchAlloc, (U8)0, sizeof(RgSchDlRbAlloc)); + cmMemset((U8 *)allocInfo->raRspAlloc, (U8)0, + RG_SCH_CMN_MAX_CMN_PDCCH*sizeof(RgSchDlRbAlloc)); + + allocInfo->msg4Alloc.msg4DlSf = NULLP; + cmLListInit(&allocInfo->msg4Alloc.msg4TxLst); + cmLListInit(&allocInfo->msg4Alloc.msg4RetxLst); + cmLListInit(&allocInfo->msg4Alloc.schdMsg4TxLst); + cmLListInit(&allocInfo->msg4Alloc.schdMsg4RetxLst); + cmLListInit(&allocInfo->msg4Alloc.nonSchdMsg4TxLst); + cmLListInit(&allocInfo->msg4Alloc.nonSchdMsg4RetxLst); +#ifdef RGR_V1 + allocInfo->ccchSduAlloc.ccchSduDlSf = NULLP; + cmLListInit(&allocInfo->ccchSduAlloc.ccchSduTxLst); + cmLListInit(&allocInfo->ccchSduAlloc.ccchSduRetxLst); + cmLListInit(&allocInfo->ccchSduAlloc.schdCcchSduTxLst); + cmLListInit(&allocInfo->ccchSduAlloc.schdCcchSduRetxLst); + cmLListInit(&allocInfo->ccchSduAlloc.nonSchdCcchSduTxLst); + cmLListInit(&allocInfo->ccchSduAlloc.nonSchdCcchSduRetxLst); +#endif + + allocInfo->dedAlloc.dedDlSf = NULLP; + cmLListInit(&allocInfo->dedAlloc.txHqPLst); + cmLListInit(&allocInfo->dedAlloc.retxHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdTxHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdRetxHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdTxHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdRetxHqPLst); + + cmLListInit(&allocInfo->dedAlloc.txRetxHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdTxRetxHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdTxRetxHqPLst); +#ifdef LTEMAC_SPS + cmLListInit(&allocInfo->dedAlloc.txSpsHqPLst); + cmLListInit(&allocInfo->dedAlloc.retxSpsHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdTxSpsHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdRetxSpsHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdTxSpsHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdRetxSpsHqPLst); +#endif + +#ifdef LTE_ADV + rgSCHLaaCmnInitDlRbAllocInfo (allocInfo); +#endif + + cmLListInit(&allocInfo->dedAlloc.errIndTxHqPLst); + cmLListInit(&allocInfo->dedAlloc.schdErrIndTxHqPLst); + cmLListInit(&allocInfo->dedAlloc.nonSchdErrIndTxHqPLst); + RETVOID; +} + +/** + * @brief Initialize the UL Allocation Information Structure. + * + * @details + * + * Function: rgSCHCmnInitUlRbAllocInfo + * Purpose: Initialize the UL Allocation Information Structure. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnUlRbAllocInfo *allocInfo + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnInitUlRbAllocInfo +( +RgSchCmnUlRbAllocInfo *allocInfo +) +#else +PUBLIC Void rgSCHCmnInitUlRbAllocInfo(allocInfo) +RgSchCmnUlRbAllocInfo *allocInfo; +#endif +{ + TRC2(rgSCHCmnInitUlRbAllocInfo); + allocInfo->sf = NULLP; + cmLListInit(&allocInfo->contResLst); + cmLListInit(&allocInfo->schdContResLst); + cmLListInit(&allocInfo->nonSchdContResLst); + cmLListInit(&allocInfo->ueLst); + cmLListInit(&allocInfo->schdUeLst); + cmLListInit(&allocInfo->nonSchdUeLst); + + RETVOID; +} + +/** + * @brief Scheduling for PUCCH group power control. + * + * @details + * + * Function: rgSCHCmnGrpPwrCntrlPucch + * Purpose: This function does group power control for PUCCH + * corresponding to the subframe for which DL UE allocations + * have happended. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGrpPwrCntrlPucch +( +RgSchCellCb *cell, +RgSchDlSf *dlSf +) +#else +PRIVATE Void rgSCHCmnGrpPwrCntrlPucch(cell, dlSf) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +#endif +{ + TRC2(rgSCHCmnGrpPwrCntrlPucch); + + rgSCHPwrGrpCntrlPucch(cell, dlSf); + + RETVOID; +} + +/** + * @brief Scheduling for PUSCH group power control. + * + * @details + * + * Function: rgSCHCmnGrpPwrCntrlPusch + * Purpose: This function does group power control, for + * the subframe for which UL allocation has (just) happened. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *ulSf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGrpPwrCntrlPusch +( +RgSchCellCb *cell, +RgSchUlSf *ulSf +) +#else +PRIVATE Void rgSCHCmnGrpPwrCntrlPusch(cell, ulSf) +RgSchCellCb *cell; +RgSchUlSf *ulSf; +#endif +{ + /*removed unused variable *cellSch*/ + CmLteTimingInfo frm; + RgSchDlSf *dlSf; + + TRC2(rgSCHCmnGrpPwrCntrlPusch); + + /* Got to pass DL SF corresponding to UL SF, so get that first. + * There is no easy way of getting dlSf by having the RgSchUlSf*, + * so use the UL delta from current time to get the DL SF. */ + frm = cell->crntTime; + +#ifdef EMTC_ENABLE + if(cell->emtcEnable == TRUE) + { + RGSCH_INCR_SUB_FRAME_EMTC(frm, TFU_DLCNTRL_DLDELTA); + } + else +#endif + { + RGSCH_INCR_SUB_FRAME(frm, TFU_DLCNTRL_DLDELTA); + } + /* Del filling of dl.time */ + dlSf = rgSCHUtlSubFrmGet(cell, frm); + + rgSCHPwrGrpCntrlPusch(cell, dlSf, ulSf); + + RETVOID; +} + +/* Fix: syed align multiple UEs to refresh at same time */ +/*********************************************************** + * + * Func : rgSCHCmnApplyUeRefresh + * + * Desc : Apply UE refresh in CMN and Specific + * schedulers. Data rates and corresponding + * scratchpad variables are updated. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnApplyUeRefresh +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE S16 rgSCHCmnApplyUeRefresh(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U32 effGbrBsr = 0; + U32 effNonGbrBsr = 0; + U32 lcgId; + + TRC2(rgSCHCmnApplyUeRefresh); + + /* Reset the refresh cycle variableCAP */ + ue->ul.effAmbr = ue->ul.cfgdAmbr; + + for (lcgId = 1; lcgId < RGSCH_MAX_LCG_PER_UE; lcgId++) + { + if (RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[lcgId])) + { + RgSchCmnLcg *cmnLcg = ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgId].sch)); + + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + cmnLcg->effGbr = cmnLcg->cfgdGbr; + cmnLcg->effDeltaMbr = cmnLcg->deltaMbr; + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, cmnLcg->effGbr + cmnLcg->effDeltaMbr); + /* Considering GBR LCG will be prioritised by UE */ + effGbrBsr += cmnLcg->bs; + }/* Else no remaing BS so nonLcg0 will be updated when BSR will be received */ + else + { + effNonGbrBsr += cmnLcg->reportedBs; + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, ue->ul.effAmbr); + } + } + } + effNonGbrBsr = RGSCH_MIN(effNonGbrBsr,ue->ul.effAmbr); + ue->ul.nonGbrLcgBs = effNonGbrBsr; + + ue->ul.nonLcg0Bs = effGbrBsr + effNonGbrBsr; + ue->ul.effBsr = ue->ul.nonLcg0Bs +\ + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs; + + + /* call scheduler specific event handlers + * for refresh timer expiry */ + cellSch->apisUl->rgSCHUlUeRefresh(cell, ue); + cellSch->apisDl->rgSCHDlUeRefresh(cell, ue); + + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnTmrExpiry + * + * Desc : Adds an UE to refresh queue, so that the UE is + * periodically triggered to refresh it's GBR and + * AMBR values. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnTmrExpiry +( +PTR cb, /* Pointer to timer control block */ +S16 tmrEvnt /* Timer Event */ +) +#else +PRIVATE S16 rgSCHCmnTmrExpiry(cb, tmrEvnt) +PTR cb; /* Pointer to timer control block */ +S16 tmrEvnt; /* Timer Event */ +#endif +{ + RgSchUeCb *ue = (RgSchUeCb *)cb; + RgSchCellCb *cell = ue->cell; +#if (ERRCLASS & ERRCLS_DEBUG) +#endif + + TRC2(rgSCHCmnTmrExpiry); + +#if (ERRCLASS & ERRCLS_DEBUG) + if (tmrEvnt != RG_SCH_CMN_EVNT_UE_REFRESH) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnTmrExpiry(): Invalid " + "timer event CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } +#else + UNUSED(tmrEvnt); +#endif + + rgSCHCmnApplyUeRefresh(cell, ue); + + rgSCHCmnAddUeToRefreshQ(cell, ue, RG_SCH_CMN_REFRESH_TIME); + + RETVALUE(ROK); +} + +/*********************************************************** + * + * Func : rgSCHCmnTmrProc + * + * Desc : Timer entry point per cell. Timer + * processing is triggered at every frame boundary + * (every 10 ms). + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnTmrProc +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnTmrProc(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnDlCell *cmnDlCell = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchCmnUlCell *cmnUlCell = RG_SCH_CMN_GET_UL_CELL(cell); + /* Moving the assignment of scheduler pointer + to available scope for optimization */ + TRC2(rgSCHCmnTmrProc); + + if ((cell->crntTime.subframe % RGSCH_NUM_SUB_FRAMES_5G) == 0) + { + /* Reset the counters periodically */ + if ((cell->crntTime.sfn % RG_SCH_CMN_CSG_REFRESH_TIME) == 0) + { + RG_SCH_RESET_HCSG_DL_PRB_CNTR(cmnDlCell); + RG_SCH_RESET_HCSG_UL_PRB_CNTR(cmnUlCell); + } + if ((cell->crntTime.sfn % RG_SCH_CMN_OVRLDCTRL_REFRESH_TIME) == 0) + { + + cell->measurements.ulTpt = ((cell->measurements.ulTpt * 95) + ( cell->measurements.ulBytesCnt * 5))/100; + cell->measurements.dlTpt = ((cell->measurements.dlTpt * 95) + ( cell->measurements.dlBytesCnt * 5))/100; + + rgSCHUtlCpuOvrLdAdjItbsCap(cell); + /* reset cell level tpt measurements for next cycle */ + cell->measurements.ulBytesCnt = 0; + cell->measurements.dlBytesCnt = 0; + } + /* Comparing with Zero instead of % is being done for efficiency. + * If Timer resolution changes then accordingly update the + * macro RG_SCH_CMN_REFRESH_TIMERES */ + RgSchCmnCell *sched = RG_SCH_CMN_GET_CELL(cell); + cmPrcTmr(&sched->tmrTqCp, sched->tmrTq, (PFV)rgSCHCmnTmrExpiry); + } + + RETVALUE(ROK); +} + + +/*********************************************************** + * + * Func : rgSchCmnUpdCfiVal + * + * Desc : Update the CFI value if CFI switch was done + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSchCmnUpdCfiVal +( +RgSchCellCb *cell, +U8 delta +) +#else +PRIVATE Void rgSchCmnUpdCfiVal(cell, delta) +RgSchCellCb *cell; +U8 delta; +#endif +{ + RgSchDlSf *dlSf; + CmLteTimingInfo pdsch; + RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 dlIdx; +#ifdef LTE_TDD + U8 mPhich; + RgSchDlSf *tddSf; + U8 idx; + U8 splSfCfi = 0; +#endif + + TRC2(rgSchCmnUpdCfiVal); + + pdsch = cell->crntTime; + RGSCH_INCR_SUB_FRAME(pdsch, delta); + dlSf = rgSCHUtlSubFrmGet(cell, pdsch); + /* Fix for DCFI FLE issue: when DL delta is 1 and UL delta is 0 and CFI + *change happens in that SF then UL PDCCH allocation happens with old CFI + *but CFI in control Req goes updated one since it was stored in the CELL + */ + dlSf->pdcchInfo.currCfi = cellCmnDl->currCfi; + if(cell->dynCfiCb.pdcchSfIdx != 0xFF) + { +#ifdef LTE_TDD + dlIdx = rgSCHUtlGetDlSfIdx(cell, &pdsch); +#else + dlIdx = (((pdsch.sfn & 1) * RGSCH_NUM_SUB_FRAMES) + (pdsch.subframe % RGSCH_NUM_SUB_FRAMES)); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx); +#endif + /* If current downlink subframe index is same as pdcch SF index, + * perform the switching of CFI in this subframe */ + if(cell->dynCfiCb.pdcchSfIdx == dlIdx) + { + cellCmnDl->currCfi = cellCmnDl->newCfi; + cell->dynCfiCb.pdcchSfIdx = 0xFF; + + /* Updating the nCce value based on the new CFI */ +#ifdef LTE_TDD + splSfCfi = cellCmnDl->newCfi; + for(idx = 0; idx < cell->numDlSubfrms; idx++) + { + tddSf = cell->subFrms[idx]; + + mPhich = rgSchTddPhichMValTbl[cell->ulDlCfgIdx][tddSf->sfNum]; + + if(tddSf->sfType == RG_SCH_SPL_SF_DATA) + { + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, splSfCfi); + + tddSf->nCce = cell->dynCfiCb.cfi2NCceTbl[mPhich][splSfCfi]; + } + else + { + tddSf->nCce = cell->dynCfiCb.cfi2NCceTbl[mPhich][cellCmnDl->currCfi]; + } + } + /* Setting the switch over window length based on config index. + * During switch over period all the UL trnsmissions are Acked + * to UEs */ + cell->dynCfiCb.switchOvrWinLen = + rgSchCfiSwitchOvrWinLen[cell->ulDlCfgIdx]; +#else + cell->nCce = cell->dynCfiCb.cfi2NCceTbl[0][cellCmnDl->currCfi]; + /* Fix for DCFI FLE issue: when DL delta is 1 and UL delta is 0 and CFI + *change happens in that SF then UL PDCCH allocation happens with old CFI + *but CFI in control Req goes updated one since it was stored in the CELL + */ + dlSf->pdcchInfo.currCfi = cellCmnDl->currCfi; + cell->dynCfiCb.switchOvrWinLen = rgSchCfiSwitchOvrWinLen[7]; +#endif + } + } + + RETVOID; +} + +/*********************************************************** + * + * Func : rgSchCmnUpdtPdcchSfIdx + * + * Desc : Update the switch over window length + * + * Ret : void + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef LTE_TDD +#ifdef ANSI +PRIVATE Void rgSchCmnUpdtPdcchSfIdx +( +RgSchCellCb *cell, +U8 dlIdx, +U8 sfNum +) +#else +PRIVATE Void rgSchCmnUpdtPdcchSfIdx(cell, dlIdx, sfNum) +RgSchCellCb *cell; +U8 dlIdx; +U8 sfNum; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSchCmnUpdtPdcchSfIdx +( +RgSchCellCb *cell, +U8 dlIdx +) +#else +PRIVATE Void rgSchCmnUpdtPdcchSfIdx(cell, dlIdx) +RgSchCellCb *cell; +U8 dlIdx; +#endif +#endif +{ + U8 idx; + + TRC2(rgSchCmnUpdtPdcchSfIdx); + + /* Resetting the parameters on CFI switching */ + cell->dynCfiCb.cceUsed = 0; + cell->dynCfiCb.lowCceCnt = 0; + + cell->dynCfiCb.cceFailSum = 0; + cell->dynCfiCb.cceFailCnt = 0; + cell->dynCfiCb.prevCceFailIdx = 0; + + cell->dynCfiCb.switchOvrInProgress = TRUE; + + for(idx = 0; idx < cell->dynCfiCb.numFailSamples; idx++) + { + cell->dynCfiCb.cceFailSamples[idx] = 0; + } + + cell->dynCfiCb.ttiCnt = 0; + + cell->dynCfiCb.cfiSwitches++; + cfiSwitchCnt = cell->dynCfiCb.cfiSwitches; + +#ifdef LTE_TDD + cell->dynCfiCb.pdcchSfIdx = (dlIdx + + rgSchTddPdcchSfIncTbl[cell->ulDlCfgIdx][sfNum]) % cell->numDlSubfrms; +#else + cell->dynCfiCb.pdcchSfIdx = (dlIdx + RG_SCH_CFI_APPLY_DELTA) % \ + RGSCH_NUM_DL_SUBFRAMES; +#endif +} + +/*********************************************************** + * + * Func : rgSchCmnUpdCfiDb + * + * Desc : Update the counters related to dynamic + * CFI feature in cellCb. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC Void rgSchCmnUpdCfiDb +( +RgSchCellCb *cell, +U8 delta +) +#else +PUBLIC Void rgSchCmnUpdCfiDb(cell, delta) +RgSchCellCb *cell; +U8 delta; +#endif +{ + CmLteTimingInfo frm; + RgSchDlSf *dlSf; +#ifdef LTE_TDD + U8 mPhich; + Bool isHiDci0; +#endif + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 nCceLowerCfi = 0; + U8 currCfi; + U8 cceFailIdx; + U32 totalCce; + U8 dlIdx; + U16 ttiMod; + + TRC2(rgSchCmnUpdCfiDb); + + /* Get Downlink Subframe */ + frm = cell->crntTime; + RGSCH_INCR_SUB_FRAME(frm, delta); + +#ifdef LTE_TDD + dlIdx = rgSCHUtlGetDlSfIdx(cell, &frm); + dlSf = cell->subFrms[dlIdx]; + isHiDci0 = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][dlSf->sfNum]; +#else + /* Changing the idexing + so that proper subframe is selected */ + dlIdx = (((frm.sfn & 1) * RGSCH_NUM_SUB_FRAMES) + (frm.subframe % RGSCH_NUM_SUB_FRAMES)); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx); + dlSf = cell->subFrms[dlIdx]; +#endif + + currCfi = cellSch->dl.currCfi; + + if(!cell->dynCfiCb.switchOvrInProgress) + { + do{ + if(!cell->dynCfiCb.isDynCfiEnb) + { + if(currCfi != cellSch->cfiCfg.cfi) + { + if(currCfi < cellSch->cfiCfg.cfi) + { + RG_SCH_CFI_STEP_UP(cell, cellSch, currCfi) + cfiIncr = cell->dynCfiCb.cfiIncr; + } + else + { + RG_SCH_CFI_STEP_DOWN(cell, cellSch, currCfi) + cfiDecr = cell->dynCfiCb.cfiDecr; + } + } + break; + } + +#ifdef LTE_TDD + /* Setting ttiMod to 0 for ttiCnt > 1000 in case if this + * function was not called in UL subframe*/ + if(cell->dynCfiCb.ttiCnt > RGSCH_CFI_TTI_MON_INTRVL) + { + ttiMod = 0; + } + else +#endif + { + ttiMod = cell->dynCfiCb.ttiCnt % RGSCH_CFI_TTI_MON_INTRVL; + } + + dlSf->dlUlBothCmplt++; +#ifdef LTE_TDD + if((dlSf->dlUlBothCmplt == 2) || (!isHiDci0)) +#else + if(dlSf->dlUlBothCmplt == 2) +#endif + { + /********************STEP UP CRITERIA********************/ + /* Updating the CCE failure count parameter */ + cell->dynCfiCb.cceFailCnt += dlSf->isCceFailure; + cell->dynCfiCb.cceFailSum += dlSf->isCceFailure; + + /* Check if cfi step up can be performed */ + if(currCfi < cell->dynCfiCb.maxCfi) + { + if(cell->dynCfiCb.cceFailSum >= cell->dynCfiCb.cfiStepUpTtiCnt) + { + RG_SCH_CFI_STEP_UP(cell, cellSch, currCfi) + cfiIncr = cell->dynCfiCb.cfiIncr; + break; + } + } + + /********************STEP DOWN CRITERIA********************/ + + /* Updating the no. of CCE used in this dl subframe */ + cell->dynCfiCb.cceUsed += dlSf->cceCnt; + + if(currCfi > RGSCH_MIN_CFI_VAL) + { + /* calculating the number of CCE for next lower CFI */ +#ifdef LTE_TDD + mPhich = rgSchTddPhichMValTbl[cell->ulDlCfgIdx][dlSf->sfNum]; + nCceLowerCfi = cell->dynCfiCb.cfi2NCceTbl[mPhich][currCfi-1]; +#else + nCceLowerCfi = cell->dynCfiCb.cfi2NCceTbl[0][currCfi-1]; +#endif + if(dlSf->cceCnt < nCceLowerCfi) + { + /* Updating the count of TTIs in which no. of CCEs + * used were less than the CCEs of next lower CFI */ + cell->dynCfiCb.lowCceCnt++; + } + + if(ttiMod == 0) + { + totalCce = (nCceLowerCfi * cell->dynCfiCb.cfiStepDownTtiCnt * + RGSCH_CFI_CCE_PERCNTG)/100; + + if((!cell->dynCfiCb.cceFailSum) && + (cell->dynCfiCb.lowCceCnt >= + cell->dynCfiCb.cfiStepDownTtiCnt) && + (cell->dynCfiCb.cceUsed < totalCce)) + { + RG_SCH_CFI_STEP_DOWN(cell, cellSch, currCfi) + cfiDecr = cell->dynCfiCb.cfiDecr; + break; + } + } + } + + cceFailIdx = ttiMod/cell->dynCfiCb.failSamplePrd; + + if(cceFailIdx != cell->dynCfiCb.prevCceFailIdx) + { + /* New sample period has started. Subtract the old count + * from the new sample period */ + cell->dynCfiCb.cceFailSum -= cell->dynCfiCb.cceFailSamples[cceFailIdx]; + + /* Store the previous sample period data */ + cell->dynCfiCb.cceFailSamples[cell->dynCfiCb.prevCceFailIdx] + = cell->dynCfiCb.cceFailCnt; + + cell->dynCfiCb.prevCceFailIdx = cceFailIdx; + + /* Resetting the CCE failure count as zero for next sample period */ + cell->dynCfiCb.cceFailCnt = 0; + } + + if(ttiMod == 0) + { + /* Restting the parametrs after Monitoring Interval expired */ + cell->dynCfiCb.cceUsed = 0; + cell->dynCfiCb.lowCceCnt = 0; + cell->dynCfiCb.ttiCnt = 0; + } + + cell->dynCfiCb.ttiCnt++; + } + }while(0); + + if(cellSch->dl.newCfi != cellSch->dl.currCfi) + { +#ifdef LTE_TDD + rgSchCmnUpdtPdcchSfIdx(cell, dlIdx, dlSf->sfNum); +#else + rgSchCmnUpdtPdcchSfIdx(cell, dlIdx); +#endif + } + } +} + +/** + * @brief Dl Scheduler for Broadcast and Common channel scheduling. + * + * @details + * + * Function: rgSCHCmnDlCommonChSch + * Purpose: This function schedules DL Common channels for LTE. + * Invoked by TTI processing in TOM. Scheduling is done for + * BCCH, PCCH, Msg4, CCCH SDU, RAR in that order + * + * Invoked by: TOM (TTI processing) + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlCommonChSch +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnDlCommonChSch(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnDlCommonChSch); + + cellSch->apisDl->rgSCHDlTickForPdbTrkng(cell); + rgSchCmnUpdCfiVal(cell, RG_SCH_CMN_DL_DELTA); + + /* handle Inactive UEs for DL */ + rgSCHCmnHdlDlInactUes(cell); + + /* Send a Tick to Refresh Timer */ + rgSCHCmnTmrProc(cell); + + if (cell->isDlDataAllwd && (cell->stopSiSch == FALSE)) + { + rgSCHCmnInitRbAlloc(cell); + /* Perform DL scheduling of BCCH, PCCH */ + rgSCHCmnDlBcchPcchAlloc(cell); + } + else + { + if(cell->siCb.inWindow != 0) + { + cell->siCb.inWindow--; + } + } + if (cell->isDlDataAllwd && (cell->stopDlSch == FALSE)) + { + rgSCHCmnDlCcchRarAlloc(cell); + } + RETVOID; +} + +/** + * @brief Scheduler invocation per TTI. + * + * @details + * + * Function: rgSCHCmnUlSch + * Purpose: This function implements UL scheduler alone. This is to + * be able to perform scheduling with more flexibility. + * + * Invoked by: TOM (TTI processing) + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlSch +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnUlSch(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnUlSch); + +#ifdef LTE_ADV + /* LAA_SCELL: */ + if(TRUE == rgSCHLaaSCellEnabled(cell)) + { + RETVOID; + } +#endif + + if(cellSch->ul.schdIdx != RGSCH_INVALID_INFO) + { + rgSchCmnUpdCfiVal(cell, TFU_ULCNTRL_DLDELTA); + + /* Handle Inactive UEs for UL */ + rgSCHCmnHdlUlInactUes(cell); + /* Perform UL Scheduling EVERY TTI */ + rgSCHCmnUlAlloc(cell); + + /* Calling function to update CFI parameters*/ + rgSchCmnUpdCfiDb(cell, TFU_ULCNTRL_DLDELTA); + + if(cell->dynCfiCb.switchOvrWinLen > 0) + { + /* Decrementing the switchover window length */ + cell->dynCfiCb.switchOvrWinLen--; + + if(!cell->dynCfiCb.switchOvrWinLen) + { + if(cell->dynCfiCb.dynCfiRecfgPend) + { + /* Toggling the Dynamic CFI enabling */ + cell->dynCfiCb.isDynCfiEnb ^= 1; + rgSCHDynCfiReCfg(cell, cell->dynCfiCb.isDynCfiEnb); + cell->dynCfiCb.dynCfiRecfgPend = FALSE; + } + cell->dynCfiCb.switchOvrInProgress = FALSE; + } + } + } +#ifdef LTE_TDD +#ifdef LTEMAC_SPS + else + { + rgSCHCmnSpsUlTti(cell, NULLP); + } +#endif +#endif + + RETVOID; +} + + +/** + * @brief This function updates the scheduler with service for an UE. + * + * @details + * + * Function: rgSCHCmnDlDedBoUpd + * Purpose: This function should be called whenever there is a + * change BO for a service. + * + * Invoked by: BO and Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ue + * @param[in] RgSchDlLcCb* svc + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlDedBoUpd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlLcCb *svc +) +#else +PUBLIC Void rgSCHCmnDlDedBoUpd(cell, ue, svc) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlLcCb *svc; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnDlDedBoUpd); + + /* RACHO : if UEs idle time exceeded and a BO update + * is received, then add UE to the pdcch Order Q */ + if (RG_SCH_CMN_IS_UE_PDCCHODR_INACTV(ue)) + { + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue, cell); + /* If PDCCH order is already triggered and we are waiting for + * RACH from UE then do not add to PdcchOdrQ. */ + if (ueDl->rachInfo.rapIdLnk.node == NULLP) + { + rgSCHCmnDlAdd2PdcchOdrQ(cell, ue); + } + } + +#ifdef LTEMAC_SPS + + /* If SPS service, invoke SPS module */ + if (svc->dlLcSpsCfg.isSpsEnabled) + { + rgSCHCmnSpsDlDedBoUpd(cell, ue, svc); + /* Note: Retrun from here, no update needed in other schedulers */ + RETVOID; + } +#endif +#ifdef EMTC_ENABLE + if((cell->emtcEnable)&&(TRUE == ue->isEmtcUe)) + { + cellSch->apisEmtcDl->rgSCHDlDedBoUpd(cell, ue, svc); + //printf("rgSCHEMTCDlDedBoUpd\n"); + } + else +#endif + { + cellSch->apisDl->rgSCHDlDedBoUpd(cell, ue, svc); + } +#ifdef LTE_ADV + if (ue->numSCells) + { + rgSCHSCellDlDedBoUpd(cell, ue, svc); + } +#endif + RETVOID; +} + + +/** + * @brief Removes an UE from Cell's TA List. + * + * @details + * + * Function: rgSCHCmnRmvFrmTaLst + * Purpose: Removes an UE from Cell's TA List. + * + * Invoked by: Specific Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnRmvFrmTaLst +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnRmvFrmTaLst(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell); + TRC2(rgSCHCmnRmvFrmTaLst); + +#ifdef EMTC_ENABLE + if(cell->emtcEnable && ue->isEmtcUe) + { + rgSCHEmtcRmvFrmTaLst(cellCmnDl,ue); + } + else +#endif + { + cmLListDelFrm(&cellCmnDl->taLst, &ue->dlTaLnk); + ue->dlTaLnk.node = (PTR)NULLP; + } + RETVOID; +} + +/* Fix: syed Remove the msg4Proc from cell + * msg4Retx Queue. I have used CMN scheduler function + * directly. Please define a new API and call this + * function through that. */ + +/** + * @brief This function removes MSG4 HARQ process from cell RETX Queues. + * + * @details + * + * Function: rgSCHCmnDlMsg4ProcRmvFrmRetx + * Purpose: This function removes MSG4 HARQ process from cell RETX Queues. + * + * Invoked by: UE/RACB deletion. + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlHqProc* hqP + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlMsg4ProcRmvFrmRetx +( +RgSchCellCb *cell, +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnDlMsg4ProcRmvFrmRetx(cell, hqP) +RgSchCellCb *cell; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnDlMsg4ProcRmvFrmRetx); + + if (hqP->tbInfo[0].ccchSchdInfo.retxLnk.node) + { + if (hqP->hqE->msg4Proc == hqP) + { + cmLListDelFrm(&cellSch->dl.msg4RetxLst, \ + &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)NULLP; + } +#ifdef RGR_V1 + else if(hqP->hqE->ccchSduProc == hqP) + { + cmLListDelFrm(&cellSch->dl.ccchSduRetxLst, + &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)NULLP; + } +#endif + } + RETVOID; +} + + +/** + * @brief This function adds a HARQ process for retx. + * + * @details + * + * Function: rgSCHCmnDlProcAddToRetx + * Purpose: This function adds a HARQ process to retransmission + * queue. This may be performed when a HARQ ack is + * unsuccessful. + * + * Invoked by: HARQ feedback processing + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchDlHqProc* hqP + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlProcAddToRetx +( +RgSchCellCb *cell, +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnDlProcAddToRetx(cell, hqP) +RgSchCellCb *cell; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnDlProcAddToRetx); + + if (hqP->hqE->msg4Proc == hqP) /* indicating msg4 transmission */ + { + cmLListAdd2Tail(&cellSch->dl.msg4RetxLst, \ + &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)hqP; + } +#ifdef RGR_V1 + else if(hqP->hqE->ccchSduProc == hqP) + { + /*If CCCH SDU being transmitted without cont res CE*/ + cmLListAdd2Tail(&cellSch->dl.ccchSduRetxLst, + &hqP->tbInfo[0].ccchSchdInfo.retxLnk); + hqP->tbInfo[0].ccchSchdInfo.retxLnk.node = (PTR)hqP; + } +#endif + else + { +#ifdef LTEMAC_SPS + if (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) + { + /* Invoke SPS module for SPS HARQ proc re-transmission handling */ + rgSCHCmnSpsDlProcAddToRetx(cell, hqP); + RETVOID; + } +#endif /* LTEMAC_SPS */ +#ifdef EMTC_ENABLE + if((TRUE == cell->emtcEnable) + && (TRUE == hqP->hqE->ue->isEmtcUe)) + { + cellSch->apisEmtcDl->rgSCHDlProcAddToRetx(cell, hqP); + } + else +#endif + { + cellSch->apisDl->rgSCHDlProcAddToRetx(cell, hqP); + } + } + RETVOID; +} + + +/** + * @brief This function performs RI validation and + * updates it to the ueCb. + * + * @details + * + * Function: rgSCHCmnDlSetUeRi + * Purpose: This function performs RI validation and + * updates it to the ueCb. + * + * Invoked by: rgSCHCmnDlCqiInd + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 ri + * @param[in] Bool isPeriodic + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlSetUeRi +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 ri, +Bool isPer +) +#else +PRIVATE Void rgSCHCmnDlSetUeRi(cell, ue, ri, isPer) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 ri; +Bool isPer; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgSchCmnUeInfo *ueSchCmn = RG_SCH_CMN_GET_CMN_UE(ue); + TRC2(rgSCHCmnDlSetUeRi); + +#ifdef TFU_UPGRADE + RgSchUePCqiCb *cqiCb = RG_SCH_GET_UE_CELL_CQI_CB(ue,cell); + UNUSED(isPer); +#endif + + + /* FIX for RRC Reconfiguration issue */ + /* ccpu00140894- During Tx Mode transition RI report will not entertained for + * specific during which SCH expecting UE can complete TX mode transition*/ + if (ue->txModeTransCmplt == FALSE) + { + RETVOID; + } + + /* Restrict the Number of TX layers to cell->numTxAntPorts. + * Protection from invalid RI values. */ + ri = RGSCH_MIN(ri, cell->numTxAntPorts); + + /* Special case of converting PMI to sane value when + * there is a switch in RI from 1 to 2 and PMI reported + * for RI=1 is invalid for RI=2 */ + if ((cell->numTxAntPorts == 2) && (ue->mimoInfo.txMode == RGR_UE_TM_4)) + { + if ((ri == 2) && ( ueDl->mimoInfo.ri == 1)) + { + ueDl->mimoInfo.pmi = (ueDl->mimoInfo.pmi < 2)? 1:2; + } + } + + /* Restrict the Number of TX layers according to the UE Category */ + ueDl->mimoInfo.ri = RGSCH_MIN(ri, rgUeCatTbl[ueSchCmn->ueCat].maxTxLyrs); +#ifdef TENB_STATS + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].riCnt[ueDl->mimoInfo.ri-1]++; + cell->tenbStats->sch.riCnt[ueDl->mimoInfo.ri-1]++; +#endif + +#ifdef TENB_STATS + ue->tenbStats->stats.nonPersistent.sch[0].riCnt[ueDl->mimoInfo.ri-1]++; + cell->tenbStats->sch.riCnt[ueDl->mimoInfo.ri-1]++; +#endif + +#ifdef TFU_UPGRADE + if (isPer) + { + /* If RI is from Periodic CQI report */ + cqiCb->perRiVal = ueDl->mimoInfo.ri; + /* Reset at every Periodic RI Reception */ + cqiCb->invalidateCqi = FALSE; + } + else + { + /* If RI is from Aperiodic CQI report */ + if (cqiCb->perRiVal != ueDl->mimoInfo.ri) + { + /* if this aperRI is different from last reported + * perRI then invalidate all CQI reports till next + * perRI */ + cqiCb->invalidateCqi = TRUE; + } + else + { + cqiCb->invalidateCqi = FALSE; + } + } +#endif + + if (ueDl->mimoInfo.ri > 1) + { + RG_SCH_CMN_UNSET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } + else if (ue->mimoInfo.txMode == RGR_UE_TM_3) /* ri == 1 */ + { + RG_SCH_CMN_SET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_RI_1); + } + + RETVOID; +} + + +/** + * @brief This function performs PMI validation and + * updates it to the ueCb. + * + * @details + * + * Function: rgSCHCmnDlSetUePmi + * Purpose: This function performs PMI validation and + * updates it to the ueCb. + * + * Invoked by: rgSCHCmnDlCqiInd + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 pmi + * @return Void + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlSetUePmi +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 pmi +) +#else +PRIVATE S16 rgSCHCmnDlSetUePmi(cell, ue, pmi) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 pmi; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlSetUePmi); + + if (ue->txModeTransCmplt == FALSE) + { + RETVALUE(RFAILED); + } + + if (cell->numTxAntPorts == 2) + { + if (pmi > 3) + { + RETVALUE(RFAILED); + } + if (ueDl->mimoInfo.ri == 2) + { + /*ccpu00118150 - MOD - changed pmi value validation from 0 to 2*/ + /* PMI 2 and 3 are invalid incase of 2 TxAnt and 2 Layered SM */ + if (pmi == 2 || pmi == 3) + { + RETVALUE(RFAILED); + } + ueDl->mimoInfo.pmi = pmi+1; + } + else + { + ueDl->mimoInfo.pmi = pmi; + } + } + else if (cell->numTxAntPorts == 4) + { + if (pmi > 15) + { + RETVALUE(RFAILED); + } + ueDl->mimoInfo.pmi = pmi; + } + /* Reset the No PMI Flag in forceTD */ + RG_SCH_CMN_UNSET_FORCE_TD(ue, cell, RG_SCH_CMN_TD_NO_PMI); + RETVALUE(ROK); +} + +/** + * @brief This function Updates the DL CQI on PUCCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlProcCqiMode10 + * + * This function updates the DL CQI on PUCCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiOnPucchInd + * + * Processing Steps: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode10 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + Bool *isCqiAvail + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode10(cell, ue, pucchCqi, isCqiAvail) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; + Bool *isCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode10 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode10(cell, ue, pucchCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlProcCqiMode10); + + if (pucchCqi->u.mode10Info.type == TFU_RPT_CQI) + { + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + /* Checking whether the decoded CQI is a value between 1 and 15*/ + if((pucchCqi->u.mode10Info.u.cqi) && (pucchCqi->u.mode10Info.u.cqi + < RG_SCH_CMN_MAX_CQI)) + { + ueDl->cqiFlag = TRUE; + ueDl->mimoInfo.cwInfo[0].cqi = pucchCqi->u.mode10Info.u.cqi; + ueDl->mimoInfo.cwInfo[1].cqi = ueDl->mimoInfo.cwInfo[0].cqi; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + } + else if (pucchCqi->u.mode10Info.type == TFU_RPT_RI) + { + if ( RG_SCH_CMN_IS_RI_VALID(pucchCqi->u.mode10Info.u.ri) ) + { + rgSCHCmnDlSetUeRi(cell, ue, pucchCqi->u.mode10Info.u.ri, + TRUE); + } + else + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Invalid RI value(%x) CRNTI:%d", + pucchCqi->u.mode10Info.u.ri,ue->ueId); + RETVOID; + } + } +} + +/** + * @brief This function Updates the DL CQI on PUCCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlProcCqiMode11 + * + * This function updates the DL CQI on PUCCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiOnPucchInd + * + * Processing Steps: + * Process CQI MODE 11 + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode11 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode11(cell, ue, pucchCqi, isCqiAvail, is2ndCwCqiAvail) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; + Bool *isCqiAvail; + Bool *is2ndCwCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode11 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode11(cell, ue, pucchCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlProcCqiMode11); + + if (pucchCqi->u.mode11Info.type == TFU_RPT_CQI) + { + ue->mimoInfo.puschFdbkVld = FALSE; + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((pucchCqi->u.mode11Info.u.cqi.cqi) && + (pucchCqi->u.mode11Info.u.cqi.cqi < RG_SCH_CMN_MAX_CQI)) + { + ueDl->cqiFlag = TRUE; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + ueDl->mimoInfo.cwInfo[0].cqi = pucchCqi->u.mode11Info.u.cqi.cqi; + if (pucchCqi->u.mode11Info.u.cqi.wideDiffCqi.pres) + { + RG_SCH_UPDT_CW2_CQI(ueDl->mimoInfo.cwInfo[0].cqi, \ + ueDl->mimoInfo.cwInfo[1].cqi, \ + pucchCqi->u.mode11Info.u.cqi.wideDiffCqi.val); +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = TRUE; +#endif + } + } + else + { + RETVOID; + } + rgSCHCmnDlSetUePmi(cell, ue, \ + pucchCqi->u.mode11Info.u.cqi.pmi); + } + else if (pucchCqi->u.mode11Info.type == TFU_RPT_RI) + { + if( RG_SCH_CMN_IS_RI_VALID(pucchCqi->u.mode11Info.u.ri)) + { + rgSCHCmnDlSetUeRi(cell, ue, pucchCqi->u.mode11Info.u.ri, + TRUE); + } + else + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "Invalid RI value(%x) CRNTI:%d", + pucchCqi->u.mode11Info.u.ri,ue->ueId); + RETVOID; + } + } +} + +/** + * @brief This function Updates the DL CQI on PUCCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlProcCqiMode20 + * + * This function updates the DL CQI on PUCCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiOnPucchInd + * + * Processing Steps: + * Process CQI MODE 20 + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode20 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + Bool *isCqiAvail + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode20(cell, ue, pucchCqi, isCqiAvail ) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; + Bool *isCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode20 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode20(cell, ue, pucchCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlProcCqiMode20); + + if (pucchCqi->u.mode20Info.type == TFU_RPT_CQI) + { + if (pucchCqi->u.mode20Info.u.cqi.isWideband) + { + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((pucchCqi->u.mode20Info.u.cqi.u.wideCqi) && + (pucchCqi->u.mode20Info.u.cqi.u.wideCqi < RG_SCH_CMN_MAX_CQI)) + { + ueDl->cqiFlag = TRUE; + ueDl->mimoInfo.cwInfo[0].cqi = pucchCqi->u.mode20Info.u.cqi.\ + u.wideCqi; + ueDl->mimoInfo.cwInfo[1].cqi = ueDl->mimoInfo.cwInfo[0].cqi; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + } + } + else if (pucchCqi->u.mode20Info.type == TFU_RPT_RI) + { + if(RG_SCH_CMN_IS_RI_VALID(pucchCqi->u.mode20Info.u.ri)) + { + rgSCHCmnDlSetUeRi(cell, ue, pucchCqi->u.mode20Info.u.ri, + TRUE); + } + else + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Invalid RI value(%x) CRNTI:%d", + pucchCqi->u.mode20Info.u.ri,ue->ueId); + RETVOID; + } + } +} + + +/** + * @brief This function Updates the DL CQI on PUCCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlProcCqiMode21 + * + * This function updates the DL CQI on PUCCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiOnPucchInd + * + * Processing Steps: + * Process CQI MODE 21 + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode21 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode21(cell, ue, pucchCqi, isCqiAvail, is2ndCwCqiAvail) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; + TfuDlCqiRpt *dlCqiRpt; + Bool *isCqiAvail; + Bool *is2ndCwCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode21 +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + ) +#else +PRIVATE INLINE Void rgSCHCmnDlProcCqiMode21(cell, ue, pucchCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlProcCqiMode21); + + if (pucchCqi->u.mode21Info.type == TFU_RPT_CQI) + { + ue->mimoInfo.puschFdbkVld = FALSE; + if (pucchCqi->u.mode21Info.u.cqi.isWideband) + { + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((pucchCqi->u.mode21Info.u.cqi.u.wideCqi.cqi) && + (pucchCqi->u.mode21Info.u.cqi.u.wideCqi.cqi < RG_SCH_CMN_MAX_CQI)) + { + ueDl->cqiFlag = TRUE; + ueDl->mimoInfo.cwInfo[0].cqi = pucchCqi->u.mode21Info.u.cqi.\ + u.wideCqi.cqi; + if (pucchCqi->u.mode21Info.u.cqi.u.wideCqi.diffCqi.pres) + { + RG_SCH_UPDT_CW2_CQI(ueDl->mimoInfo.cwInfo[0].cqi, \ + ueDl->mimoInfo.cwInfo[1].cqi, \ + pucchCqi->u.mode21Info.u.cqi.u.wideCqi.diffCqi.val); +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = TRUE; +#endif + } + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + rgSCHCmnDlSetUePmi(cell, ue, \ + pucchCqi->u.mode21Info.u.cqi.u.wideCqi.pmi); + } + } + else if (pucchCqi->u.mode21Info.type == TFU_RPT_RI) + { + if(RG_SCH_CMN_IS_RI_VALID(pucchCqi->u.mode21Info.u.ri)) + { + rgSCHCmnDlSetUeRi(cell, ue, pucchCqi->u.mode21Info.u.ri, + TRUE); + } + else + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "Invalid RI value(%x) CRNTI:%d", + pucchCqi->u.mode21Info.u.ri,ue->ueId); + RETVOID; + } + } +} + + +/** + * @brief This function Updates the DL CQI on PUCCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlCqiOnPucchInd + * + * This function updates the DL CQI on PUCCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiInd + * + * Processing Steps: + * - Depending on the reporting mode of the PUCCH, the CQI/PMI/RI values + * are updated and stored for each UE + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCqiOnPucchInd +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi, + RgrUeCqiRept *ueCqiRept, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + ) +#else +PRIVATE Void rgSCHCmnDlCqiOnPucchInd(cell, ue, pucchCqi, ueCqiRept, isCqiAvail, is2ndCwCqiAvail) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; + RgrUeCqiRept *ueCqiRept; + Bool *isCqiAvail; + Bool *is2ndCwCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCqiOnPucchInd +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPucch *pucchCqi + ) +#else +PRIVATE Void rgSCHCmnDlCqiOnPucchInd(cell, ue, pucchCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPucch *pucchCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + TRC2(rgSCHCmnDlCqiOnPucchInd); + + /* ccpu00117452 - MOD - Changed + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* Save CQI mode information in the report */ + ueCqiRept->cqiMode = pucchCqi->mode; +#endif + + switch(pucchCqi->mode) + { + case TFU_PUCCH_CQI_MODE10: +#ifdef RGR_CQI_REPT + rgSCHCmnDlProcCqiMode10(cell, ue, pucchCqi, isCqiAvail); +#else + rgSCHCmnDlProcCqiMode10(cell, ue, pucchCqi); +#endif + ueDl->cqiFlag = TRUE; + break; + case TFU_PUCCH_CQI_MODE11: +#ifdef RGR_CQI_REPT + rgSCHCmnDlProcCqiMode11(cell, ue, pucchCqi, isCqiAvail, + is2ndCwCqiAvail); +#else + rgSCHCmnDlProcCqiMode11(cell, ue, pucchCqi); +#endif + ueDl->cqiFlag = TRUE; + break; + case TFU_PUCCH_CQI_MODE20: +#ifdef RGR_CQI_REPT + rgSCHCmnDlProcCqiMode20(cell, ue, pucchCqi, isCqiAvail); +#else + rgSCHCmnDlProcCqiMode20(cell, ue, pucchCqi); +#endif + ueDl->cqiFlag = TRUE; + break; + case TFU_PUCCH_CQI_MODE21: +#ifdef RGR_CQI_REPT + rgSCHCmnDlProcCqiMode21(cell, ue, pucchCqi, isCqiAvail, + is2ndCwCqiAvail); +#else + rgSCHCmnDlProcCqiMode21(cell, ue, pucchCqi); +#endif + ueDl->cqiFlag = TRUE; + break; + default: + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Unknown CQI Mode %d", + pucchCqi->mode,ue->ueId); + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = FALSE; +#endif + } + break; + } + + RETVOID; +} /* rgSCHCmnDlCqiOnPucchInd */ + + +/** + * @brief This function Updates the DL CQI on PUSCH for the UE. + * + * @details + * + * Function: rgSCHCmnDlCqiOnPuschInd + * + * This function updates the DL CQI on PUSCH for the UE. + * + * Invoked by: rgSCHCmnDlCqiInd + * + * Processing Steps: + * - Depending on the reporting mode of the PUSCH, the CQI/PMI/RI values + * are updated and stored for each UE + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqiRpt + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef RGR_CQI_REPT +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCqiOnPuschInd +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPusch *puschCqi, + RgrUeCqiRept *ueCqiRept, + Bool *isCqiAvail, + Bool *is2ndCwCqiAvail + ) +#else +PRIVATE Void rgSCHCmnDlCqiOnPuschInd(cell, ue, puschCqi, ueCqiRept, isCqiAvail, is2ndCwCqiAvail) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPusch *puschCqi; + RgrUeCqiRept *ueCqiRept; + Bool *isCqiAvail; + Bool *is2ndCwCqiAvail; +#endif +#else +#ifdef ANSI +PRIVATE Void rgSCHCmnDlCqiOnPuschInd +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuDlCqiPusch *puschCqi + ) +#else +PRIVATE Void rgSCHCmnDlCqiOnPuschInd(cell, ue, puschCqi) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuDlCqiPusch *puschCqi; +#endif +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U32 prevRiVal = 0; + TRC2(rgSCHCmnDlCqiOnPuschInd); + if (puschCqi->ri.pres == PRSNT_NODEF) + { + if (RG_SCH_CMN_IS_RI_VALID(puschCqi->ri.val)) + { + /* Saving the previous ri value to revert back + in case PMI update failed */ + if (RGR_UE_TM_4 == ue->mimoInfo.txMode ) /* Cheking for TM4. TM8 check later */ + { + prevRiVal = ueDl->mimoInfo.ri; + } + rgSCHCmnDlSetUeRi(cell, ue, puschCqi->ri.val, FALSE); + } + else + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,"Invalid RI value(%x) CRNTI:%d", + puschCqi->ri.val,ue->ueId); + RETVOID; + } + } + ue->mimoInfo.puschFdbkVld = FALSE; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* Save CQI mode information in the report */ + ueCqiRept->cqiMode = puschCqi->mode; + /* ccpu00117259 - DEL - removed default setting of isCqiAvail to TRUE */ +#endif + + switch(puschCqi->mode) + { + case TFU_PUSCH_CQI_MODE_20: + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + /* Checking whether the decoded CQI is a value between 1 and 15*/ + if((puschCqi->u.mode20Info.wideBandCqi) && + (puschCqi->u.mode20Info.wideBandCqi < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[0].cqi = puschCqi->u.mode20Info.wideBandCqi; + ueDl->mimoInfo.cwInfo[1].cqi = ueDl->mimoInfo.cwInfo[0].cqi; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + break; + case TFU_PUSCH_CQI_MODE_30: + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((puschCqi->u.mode30Info.wideBandCqi) && + (puschCqi->u.mode30Info.wideBandCqi < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[0].cqi = puschCqi->u.mode30Info.wideBandCqi; + ueDl->mimoInfo.cwInfo[1].cqi = ueDl->mimoInfo.cwInfo[0].cqi; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif +#ifdef CA_DBG + { + extern U32 gACqiRcvdCount; + gACqiRcvdCount++; + + } +#endif + } + else + { + RETVOID; + } + break; + case TFU_PUSCH_CQI_MODE_12: + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((puschCqi->u.mode12Info.cqiIdx[0]) && + (puschCqi->u.mode12Info.cqiIdx[0] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[0].cqi = puschCqi->u.mode12Info.cqiIdx[0]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + if((puschCqi->u.mode12Info.cqiIdx[1]) && + (puschCqi->u.mode12Info.cqiIdx[1] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[1].cqi = puschCqi->u.mode12Info.cqiIdx[1]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + ue->mimoInfo.puschFdbkVld = TRUE; + ue->mimoInfo.puschPmiInfo.mode = TFU_PUSCH_CQI_MODE_12; + ue->mimoInfo.puschPmiInfo.u.mode12Info = puschCqi->u.mode12Info; + /* : resetting this is time based. Make use of CQI reporting + * periodicity, DELTA's in determining the exact time at which this + * need to be reset. */ + break; + case TFU_PUSCH_CQI_MODE_22: + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((puschCqi->u.mode22Info.wideBandCqi[0]) && + (puschCqi->u.mode22Info.wideBandCqi[0] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[0].cqi = puschCqi->u.mode22Info.wideBandCqi[0]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + if((puschCqi->u.mode22Info.wideBandCqi[1]) && + (puschCqi->u.mode22Info.wideBandCqi[1] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[1].cqi = puschCqi->u.mode22Info.wideBandCqi[1]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = TRUE; +#endif + } + else + { + RETVOID; + } + rgSCHCmnDlSetUePmi(cell, ue, puschCqi->u.mode22Info.wideBandPmi); + ue->mimoInfo.puschFdbkVld = TRUE; + ue->mimoInfo.puschPmiInfo.mode = TFU_PUSCH_CQI_MODE_22; + ue->mimoInfo.puschPmiInfo.u.mode22Info = puschCqi->u.mode22Info; + break; + case TFU_PUSCH_CQI_MODE_31: + /*ccpu00109787 - ADD - Check for non-zero CQI*/ + if((puschCqi->u.mode31Info.wideBandCqi[0]) && + (puschCqi->u.mode31Info.wideBandCqi[0] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[0].cqi = puschCqi->u.mode31Info.wideBandCqi[0]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = TRUE; +#endif + } + if (ueDl->mimoInfo.ri > 1) + { + if((puschCqi->u.mode31Info.wideBandCqi[1]) && + (puschCqi->u.mode31Info.wideBandCqi[1] < RG_SCH_CMN_MAX_CQI)) + { + ueDl->mimoInfo.cwInfo[1].cqi = puschCqi->u.mode31Info.wideBandCqi[1]; + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = TRUE; +#endif + } + } + if (rgSCHCmnDlSetUePmi(cell, ue, puschCqi->u.mode31Info.pmi) != ROK) + { + /* To avoid Rank and PMI inconsistency */ + if ((puschCqi->ri.pres == PRSNT_NODEF) && + (RGR_UE_TM_4 == ue->mimoInfo.txMode)) /* checking for TM4. TM8 check later */ + { + ueDl->mimoInfo.ri = prevRiVal; + } + } + ue->mimoInfo.puschPmiInfo.mode = TFU_PUSCH_CQI_MODE_31; + ue->mimoInfo.puschPmiInfo.u.mode31Info = puschCqi->u.mode31Info; + break; + default: + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "Unknown CQI Mode %d CRNTI:%d", + puschCqi->mode,ue->ueId); + /* CQI decoding failed revert the RI to previous value */ + if ((puschCqi->ri.pres == PRSNT_NODEF) && + (RGR_UE_TM_4 == ue->mimoInfo.txMode)) /* checking for TM4. TM8 check later */ + { + ueDl->mimoInfo.ri = prevRiVal; + } + /* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + *isCqiAvail = FALSE; + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + *is2ndCwCqiAvail = FALSE; +#endif + } + break; + } + + RETVOID; +} /* rgSCHCmnDlCqiOnPuschInd */ + + +/** + * @brief This function Updates the DL CQI for the UE. + * + * @details + * + * Function: rgSCHCmnDlCqiInd + * Purpose: Updates the DL CQI for the UE + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuDlCqiRpt *dlCqi + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlCqiInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +Bool isPucchInfo, +Void *dlCqi, +CmLteTimingInfo timingInfo +) +#else +PUBLIC Void rgSCHCmnDlCqiInd(cell, ue, isPucchInfo, dlCqi, timingInfo) +RgSchCellCb *cell; +RgSchUeCb *ue; +Bool isPucchInfo; +Void *dlCqi; +CmLteTimingInfo timingInfo; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); +/* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgrUeCqiRept ueCqiRept = {{0}}; + Bool isCqiAvail = FALSE; + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting */ + Bool is2ndCwCqiAvail = FALSE; +#endif + + TRC2(rgSCHCmnDlCqiInd); + +#ifdef RGR_CQI_REPT + if (isPucchInfo) + { + rgSCHCmnDlCqiOnPucchInd(cell, ue, (TfuDlCqiPucch *)dlCqi, &ueCqiRept, &isCqiAvail, &is2ndCwCqiAvail); + } + else + { + rgSCHCmnDlCqiOnPuschInd(cell, ue, (TfuDlCqiPusch *)dlCqi, &ueCqiRept, &isCqiAvail, &is2ndCwCqiAvail); + } +#else + if (isPucchInfo) + { + rgSCHCmnDlCqiOnPucchInd(cell, ue, (TfuDlCqiPucch *)dlCqi); + } + else + { + rgSCHCmnDlCqiOnPuschInd(cell, ue, (TfuDlCqiPusch *)dlCqi); + } +#endif + +#ifdef CQI_CONFBITMASK_DROP + if(!ue->cqiConfBitMask) + { + if (ueDl->mimoInfo.cwInfo[0].cqi >15) + { + ueDl->mimoInfo.cwInfo[0].cqi = ue->prevCqi; + ueDl->mimoInfo.cwInfo[1].cqi = ue->prevCqi; + } + else if ( ueDl->mimoInfo.cwInfo[0].cqi >= ue->prevCqi) + { + ue->prevCqi = ueDl->mimoInfo.cwInfo[0].cqi; + } + else + { + U8 dlCqiDeltaPrev = 0; + dlCqiDeltaPrev = ue->prevCqi - ueDl->mimoInfo.cwInfo[0].cqi; + if (dlCqiDeltaPrev > 3) + dlCqiDeltaPrev = 3; + if ((ue->prevCqi - dlCqiDeltaPrev) < 6) + { + ue->prevCqi = 6; + } + else + { + ue->prevCqi = ue->prevCqi - dlCqiDeltaPrev; + } + ueDl->mimoInfo.cwInfo[0].cqi = ue->prevCqi; + ueDl->mimoInfo.cwInfo[1].cqi = ue->prevCqi; + + } + } +#endif + +/* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting - added is2ndCwCqiAvail\ + in 'if' condition*/ + if (RG_SCH_CQIR_IS_PUSHNCQI_ENBLE(ue) && (isCqiAvail || is2ndCwCqiAvail)) + { + ueCqiRept.cqi[0] = ueDl->mimoInfo.cwInfo[0].cqi; + + /* ccpu00117259 - ADD - Considering second codeword CQI info + incase of MIMO for CQI Reporting - added is2ndCwCqiAvail + in 'if' condition*/ + ueCqiRept.cqi[1] = 0; + if(is2ndCwCqiAvail) + { + ueCqiRept.cqi[1] = ueDl->mimoInfo.cwInfo[1].cqi; + } + rgSCHCmnUeDlPwrCtColltCqiRept(cell, ue, &ueCqiRept); + + } +#endif +#ifdef DL_LA + rgSCHCmnDlSetUeAllocLmtLa(cell, ue); + rgSCHCheckAndSetTxScheme(cell, ue); +#else +#ifdef EMTC_ENABLE + rgSCHCmnDlSetUeAllocLmt(cell, RG_SCH_CMN_GET_DL_UE(ue,cell), ue->isEmtcUe); +#else + rgSCHCmnDlSetUeAllocLmt(cell, RG_SCH_CMN_GET_DL_UE(ue,cell), FALSE); +#endif +#endif + + if (cellSch->dl.isDlFreqSel) + { + cellSch->apisDlfs->rgSCHDlfsDlCqiInd(cell, ue, isPucchInfo, dlCqi, timingInfo); + } +#ifdef LTEMAC_SPS + /* Call SPS module to update CQI indication */ + rgSCHCmnSpsDlCqiIndHndlr(cell, ue, timingInfo); +#endif + /* Call Specific scheduler to process on dlCqiInd */ +#ifdef EMTC_ENABLE + if((TRUE == cell->emtcEnable) && (TRUE == ue->isEmtcUe)) + { + cellSch->apisEmtcDl->rgSCHDlCqiInd(cell, ue, isPucchInfo, dlCqi); + } + else +#endif + { + cellSch->apisDl->rgSCHDlCqiInd(cell, ue, isPucchInfo, dlCqi); + } + +#ifdef RG_PFS_STATS + ue->pfsStats.cqiStats[(RG_SCH_GET_SCELL_INDEX(ue, cell))].avgCqi += + ueDl->mimoInfo.cwInfo[0].cqi; + ue->pfsStats.cqiStats[(RG_SCH_GET_SCELL_INDEX(ue, cell))].totalCqiOcc++; +#endif + +#ifdef SCH_STATS + ueDl->avgCqi += ueDl->mimoInfo.cwInfo[0].cqi; + ueDl->numCqiOccns++; + if (ueDl->mimoInfo.ri == 1) + { + ueDl->numRi1++; + } + else + { + ueDl->numRi2++; + } +#endif + +#ifdef TENB_STATS + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].dlSumCw0Cqi += ueDl->mimoInfo.cwInfo[0].cqi; + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].dlSumCw1Cqi += ueDl->mimoInfo.cwInfo[1].cqi; + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].dlNumCw0Cqi ++; + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].dlNumCw1Cqi ++; + cell->tenbStats->sch.dlSumCw0Cqi += ueDl->mimoInfo.cwInfo[0].cqi; + cell->tenbStats->sch.dlSumCw1Cqi += ueDl->mimoInfo.cwInfo[1].cqi; + cell->tenbStats->sch.dlNumCw0Cqi ++; + cell->tenbStats->sch.dlNumCw1Cqi ++; +#endif + RETVOID; +} + +#ifdef TFU_UPGRADE +/** + * @brief This function calculates the wideband CQI from SNR + * reported for each RB. + * + * @details + * + * Function: rgSCHCmnCalcWcqiFrmSnr + * Purpose: Wideband CQI calculation from SNR + * + * Invoked by: RG SCH + * + * @param[in] RgSchCellCb *cell + * @param[in] TfuSrsRpt *srsRpt, + * @return Wideband CQI + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnCalcWcqiFrmSnr +( + RgSchCellCb *cell, + TfuSrsRpt *srsRpt + ) +#else +PRIVATE U8 rgSCHCmnCalcWcqiFrmSnr(cell,srsRpt) + RgSchCellCb *cell; + TfuSrsRpt *srsRpt; +#endif +{ + U8 wideCqi=1; /*Calculated value from SNR*/ + TRC2(rgSCHCmnCalcWcqiFrmSnr); + /*Need to map a certain SNR with a WideCQI value. + * The CQI calculation is still primitive. Further, need to + * use a improvized method for calculating WideCQI from SNR*/ + if (srsRpt->snr[0] <=50) + { + wideCqi=3; + } + else if (srsRpt->snr[0]>=51 && srsRpt->snr[0] <=100) + { + wideCqi=6; + } + else if (srsRpt->snr[0]>=101 && srsRpt->snr[0] <=150) + { + wideCqi=9; + } + else if (srsRpt->snr[0]>=151 && srsRpt->snr[0] <=200) + { + wideCqi=12; + } + else if (srsRpt->snr[0]>=201 && srsRpt->snr[0] <=250) + { + wideCqi=14; + } + else + { + wideCqi=15; + } + RETVALUE(wideCqi); +}/*rgSCHCmnCalcWcqiFrmSnr*/ + + +/** + * @brief This function Updates the SRS for the UE. + * + * @details + * + * Function: rgSCHCmnSrsInd + * Purpose: Updates the UL SRS for the UE + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuSrsRpt *srsRpt, + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnSrsInd +( + RgSchCellCb *cell, + RgSchUeCb *ue, + TfuSrsRpt *srsRpt, + CmLteTimingInfo timingInfo + ) +#else +PUBLIC Void rgSCHCmnSrsInd(cell, ue, srsRpt, timingInfo) + RgSchCellCb *cell; + RgSchUeCb *ue; + TfuSrsRpt *srsRpt; + CmLteTimingInfo timingInfo; +#endif +{ + U8 wideCqi; /*Calculated value from SNR*/ + U32 recReqTime; /*Received Time in TTI*/ + TRC2(rgSCHCmnSrsInd); + + recReqTime = (timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G) + timingInfo.subframe; + ue->srsCb.selectedAnt = (recReqTime/ue->srsCb.peri)%2; + if(srsRpt->wideCqiPres) + { + wideCqi = srsRpt->wideCqi; + } + else + { + wideCqi = rgSCHCmnCalcWcqiFrmSnr(cell, srsRpt); + } + rgSCHCmnFindUlCqiUlTxAnt(cell, ue, wideCqi); + RETVOID; +}/*rgSCHCmnSrsInd*/ +#endif + + +/** + * @brief This function is a handler for TA report for an UE. + * + * @details + * + * Function: rgSCHCmnDlTARpt + * Purpose: Determine based on UE_IDLE_TIME threshold, + * whether UE needs to be Linked to the scheduler's TA list OR + * if it needs a PDCCH Order. + * + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlTARpt +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnDlTARpt(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + CmLListCp poInactvLst; + + TRC2(rgSCHCmnDlTARpt); + + /* RACHO: If UE idle time is more than threshold, then + * set its poInactv pdcch order inactivity */ + /* Fix : syed Ignore if TaTmr is not configured */ + if ((ue->dl.taCb.cfgTaTmr) && (rgSCHCmnUeIdleExdThrsld(cell, ue) == ROK)) + { + U32 prevDlMsk = ue->dl.dlInactvMask; + U32 prevUlMsk = ue->ul.ulInactvMask; + ue->dl.dlInactvMask |= RG_PDCCHODR_INACTIVE; + ue->ul.ulInactvMask |= RG_PDCCHODR_INACTIVE; + /* Indicate Specific scheduler for this UEs inactivity */ + cmLListInit(&poInactvLst); + cmLListAdd2Tail(&poInactvLst, &ueDl->rachInfo.inActUeLnk); + ueDl->rachInfo.inActUeLnk.node = (PTR)ue; + /* Send inactivate ind only if not already sent */ + if (prevDlMsk == 0) + { + cellSch->apisDl->rgSCHDlInactvtUes(cell, &poInactvLst); + } + if (prevUlMsk == 0) + { + cellSch->apisUl->rgSCHUlInactvtUes(cell, &poInactvLst); + } + } + else + { + /* Fix: ccpu00124009 Fix for loop in the linked list "cellDl->taLst" */ + if (!ue->dlTaLnk.node) + { +#ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + rgSCHEmtcAddToTaLst(cellDl,ue); + } + } + else +#endif + { + + cmLListAdd2Tail(&cellDl->taLst, &ue->dlTaLnk); + ue->dlTaLnk.node = (PTR)ue; + } + } + else + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "TA duplicate entry attempt failed: UEID:%u", + ue->ueId); + } + } + RETVOID; +} + +#ifdef TFU_UPGRADE +/** + * @brief Indication of UL CQI. + * + * @details + * + * Function : rgSCHCmnFindUlCqiUlTxAnt + * + * - Finds the Best Tx Antenna amongst the CQIs received + * from Two Tx Antennas. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 wideCqi + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFindUlCqiUlTxAnt +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 wideCqi +) +#else +PRIVATE Void rgSCHCmnFindUlCqiUlTxAnt(cell, ue, wideCqi) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 wideCqi; +#endif +{ + ue->validTxAnt = 1; + RETVOID; +} /* rgSCHCmnFindUlCqiUlTxAnt */ +#endif + +/** + * @brief Indication of UL CQI. + * + * @details + * + * Function : rgSCHCmnUlCqiInd + * + * - Updates uplink CQI information for the UE. Computes and + * stores the lowest CQI of CQIs reported in all subbands. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] TfuUlCqiRpt *ulCqiInfo + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlCqiInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +TfuUlCqiRpt *ulCqiInfo +) +#else +PUBLIC Void rgSCHCmnUlCqiInd(cell, ue, ulCqiInfo) +RgSchCellCb *cell; +RgSchUeCb *ue; +TfuUlCqiRpt *ulCqiInfo; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); +#ifdef UL_LA + U8 iTbsNew; + S32 previTbs; +#endif +#if (defined(SCH_STATS) || defined(TENB_STATS)) + CmLteUeCategory ueCtg = (CmLteUeCategory)(RG_SCH_CMN_GET_UE_CTGY(ue)); +#endif + + TRC2(rgSCHCmnUlCqiInd); + /* consider inputs from SRS handlers about SRS occassions + * in determining the UL TX Antenna selection */ + ueUl->crntUlCqi[0] = ulCqiInfo->wideCqi; +#ifdef TFU_UPGRADE + ueUl->validUlCqi = ueUl->crntUlCqi[0]; + ue->validTxAnt = 0; +#ifdef UL_LA + iTbsNew = rgSchCmnUlCqiToTbsTbl[cell->isCpUlExtend][ueUl->validUlCqi]; + previTbs = (ueUl->ulLaCb.cqiBasediTbs + ueUl->ulLaCb.deltaiTbs)/100; + + if (RG_ITBS_DIFF(iTbsNew, previTbs) > 5) + { + /* Ignore this iTBS report and mark that last iTBS report was */ + /* ignored so that subsequently we reset the LA algorithm */ + ueUl->ulLaCb.lastiTbsIgnored = TRUE; + } + else + { + if (ueUl->ulLaCb.lastiTbsIgnored != TRUE) + { + ueUl->ulLaCb.cqiBasediTbs = ((20 * iTbsNew * 100) + + (80 * ueUl->ulLaCb.cqiBasediTbs))/100; + } + else + { + /* Reset the LA as iTbs in use caught up with the value */ + /* reported by UE. */ + ueUl->ulLaCb.cqiBasediTbs = ((20 * iTbsNew * 100) + + (80 * previTbs * 100))/100; + ueUl->ulLaCb.deltaiTbs = 0; + ueUl->ulLaCb.lastiTbsIgnored = FALSE; + } + } +#endif +#endif + rgSCHPwrUlCqiInd(cell, ue); +#ifdef LTEMAC_SPS + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlCqiInd(cell, ue); + } +#endif + /* Applicable to only some schedulers */ +#ifdef EMTC_ENABLE + if((TRUE == cell->emtcEnable) && (TRUE == ue->isEmtcUe)) + { + cellSch->apisEmtcUl->rgSCHUlCqiInd(cell, ue, ulCqiInfo); + } + else +#endif + { + cellSch->apisUl->rgSCHUlCqiInd(cell, ue, ulCqiInfo); + } + +#ifdef SCH_STATS + ueUl->numCqiOccns++; + ueUl->avgCqi += rgSCHCmnUlGetCqi(cell, ue, ueCtg); +#endif + +#ifdef TENB_STATS + { + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].ulSumCqi += rgSCHCmnUlGetCqi(cell, ue, ueCtg); + ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(cell)].ulNumCqi ++; + cell->tenbStats->sch.ulSumCqi += rgSCHCmnUlGetCqi(cell, ue, ueCtg); + cell->tenbStats->sch.ulNumCqi ++; + } +#endif + + RETVOID; +} /* rgSCHCmnUlCqiInd */ + +/** + * @brief Returns HARQ proc for which data expected now. + * + * @details + * + * Function: rgSCHCmnUlHqProcForUe + * Purpose: This function returns the harq process for + * which data is expected in the current subframe. + * It does not validate that the HARQ process + * has an allocation. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] CmLteTimingInfo frm + * @param[in] RgSchUeCb *ue + * @param[out] RgSchUlHqProcCb **procRef + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlHqProcForUe +( +RgSchCellCb *cell, +CmLteTimingInfo frm, +RgSchUeCb *ue, +RgSchUlHqProcCb **procRef +) +#else +PUBLIC Void rgSCHCmnUlHqProcForUe(cell, frm, ue, procRef) +RgSchCellCb *cell; +CmLteTimingInfo frm; +RgSchUeCb *ue; +RgSchUlHqProcCb **procRef; +#endif +{ +#ifndef RG_5GTF + U8 procId = rgSCHCmnGetUlHqProcIdx(&frm, cell); +#endif + TRC2(rgSCHCmnUlHqProcForUe); +#ifndef RG_5GTF + *procRef = rgSCHUhmGetUlHqProc(cell, ue, procId); +#else + *procRef = rgSCHUhmGetUlProcByTime(cell, ue, frm); +#endif + RETVOID; +} + +#ifdef RG_UNUSED +/** + * @brief Update harq process for allocation. + * + * @details + * + * Function : rgSCHCmnUpdUlHqProc + * + * This function is invoked when harq process + * control block is now in a new memory location + * thus requiring a pointer/reference update. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlHqProcCb *curProc + * @param[in] RgSchUlHqProcCb *oldProc + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdUlHqProc +( +RgSchCellCb *cell, +RgSchUlHqProcCb *curProc, +RgSchUlHqProcCb *oldProc +) +#else +PUBLIC S16 rgSCHCmnUpdUlHqProc(cell, curProc, oldProc) +RgSchCellCb *cell; +RgSchUlHqProcCb *curProc; +RgSchUlHqProcCb *oldProc; +#endif +{ + TRC2(rgSCHCmnUpdUlHqProc); + + UNUSED(cell); + UNUSED(oldProc); +#if (ERRCLASS & ERRCLS_DEBUG) + if (curProc->alloc == NULLP) + { + RETVALUE(RFAILED); + } +#endif + curProc->alloc->hqProc = curProc; + RETVALUE(ROK); +} /* rgSCHCmnUpdUlHqProc */ +#endif + +/*MS_WORKAROUND for CR FIXME */ +/** + * @brief Hsndles BSR timer expiry + * + * @details + * + * Function : rgSCHCmnBsrTmrExpry + * + * This function is invoked when periodic BSR timer expires for a UE. + * + * @param[in] RgSchUeCb *ue + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnBsrTmrExpry +( +RgSchUeCb *ueCb +) +#else +PUBLIC S16 rgSCHCmnBsrTmrExpry(ueCb) +RgSchUeCb *ueCb; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(ueCb->cell); + + TRC2(rgSCHCmnBsrTmrExpry) + + ueCb->isSrGrant = TRUE; + +#ifdef EMTC_ENABLE + emtcStatsUlBsrTmrTxp++; +#endif + +#ifdef EMTC_ENABLE + if(ueCb->cell->emtcEnable) + { + if(ueCb->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHSrRcvd(ueCb->cell, ueCb); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHSrRcvd(ueCb->cell, ueCb); + } + + RETVALUE (ROK); +} + +/** + * @brief Short BSR update. + * + * @details + * + * Function : rgSCHCmnUpdBsrShort + * + * This functions does requisite updates to handle short BSR reporting. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchLcgCb *ulLcg + * @param[in] U8 bsr + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdBsrShort +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchLcgCb *ulLcg, +U8 bsr, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnUpdBsrShort(cell, ue, ulLcg, bsr, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchLcgCb *ulLcg; +U8 bsr; +RgSchErrInfo *err; +#endif +{ + U8 lcgCnt; +#ifdef LTE_L2_MEAS + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); +#endif + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnLcg *cmnLcg = NULLP; + +#ifdef LTE_L2_MEAS + U8 idx; +#endif + TRC2(rgSCHCmnUpdBsrShort); + + if (!RGSCH_LCG_ISCFGD(ulLcg)) + { + err->errCause = RGSCHERR_SCH_LCG_NOT_CFGD; + RETVALUE(RFAILED); + } + for (lcgCnt=0; lcgCnt<4; lcgCnt++) + { +#ifdef LTE_L2_MEAS + /* Set BS of all other LCGs to Zero. + If Zero BSR is reported in Short BSR include this LCG too */ + if ((lcgCnt != ulLcg->lcgId) || + (!bsr && !ueUl->hqEnt.numBusyHqProcs)) + { + /* If old BO is zero do nothing */ + if(((RgSchCmnLcg *)(ue->ul.lcgArr[lcgCnt].sch))->bs != 0) + { + for(idx = 0; idx < ue->ul.lcgArr[lcgCnt].numLch; idx++) + { + if((ue->ul.lcgArr[lcgCnt].lcArray[idx]->qciCb->ulUeCount) && + (ue->ulActiveLCs & (1 << + (ue->ul.lcgArr[lcgCnt].lcArray[idx]->qciCb->qci -1)))) + { + /* L2_COUNTER */ + ue->ul.lcgArr[lcgCnt].lcArray[idx]->qciCb->ulUeCount--; + ue->ulActiveLCs &= ~(1 << + (ue->ul.lcgArr[lcgCnt].lcArray[idx]->qciCb->qci -1)); + } + } + } + } +#endif + if (RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[lcgCnt])) + { + ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgCnt].sch))->bs = 0; + ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgCnt].sch))->reportedBs = 0; + } + } + +#ifdef LTE_L2_MEAS + if(ulLcg->lcgId && bsr && (((RgSchCmnLcg *)(ulLcg->sch))->bs == 0)) + { + for(idx = 0; idx < ulLcg->numLch; idx++) + { + /* L2_COUNTER */ + if (!(ue->ulActiveLCs & (1 << (ulLcg->lcArray[idx]->qciCb->qci -1)))) + { + ulLcg->lcArray[idx]->qciCb->ulUeCount++; + ue->ulActiveLCs |= (1 << (ulLcg->lcArray[idx]->qciCb->qci -1)); + } + } + } +#endif + /* Resetting the nonGbrLcgBs info here */ + ue->ul.nonGbrLcgBs = 0; + ue->ul.nonLcg0Bs = 0; + + cmnLcg = ((RgSchCmnLcg *)(ulLcg->sch)); + + if (TRUE == ue->ul.useExtBSRSizes) + { + cmnLcg->reportedBs = rgSchCmnExtBsrTbl[bsr]; + } + else + { + cmnLcg->reportedBs = rgSchCmnBsrTbl[bsr]; + } + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + /* TBD check for effGbr != 0 */ + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, cmnLcg->effGbr + cmnLcg->effDeltaMbr); + } + else if (0 == ulLcg->lcgId) + { + /* This is added for handling LCG0 */ + cmnLcg->bs = cmnLcg->reportedBs; + } + else + { + /* Update non GBR LCG's BS*/ + ue->ul.nonGbrLcgBs = RGSCH_MIN(cmnLcg->reportedBs,ue->ul.effAmbr); + cmnLcg->bs = ue->ul.nonGbrLcgBs; + } + ue->ul.totalBsr = cmnLcg->bs; + +#ifdef RGR_V1 + if ((ue->bsrTmr.tmrEvnt != TMR_NONE) && (bsr == 0)) + { + rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue); + } +#endif +#ifdef LTEMAC_SPS + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsBsrRpt(cell, ue, ulLcg); + } +#endif + rgSCHCmnUpdUlCompEffBsr(ue); + +#ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHUpdBsrShort(cell, ue, ulLcg, bsr); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHUpdBsrShort(cell, ue, ulLcg, bsr); + } + +#ifdef LTE_ADV + if (ue->ul.isUlCaEnabled && ue->numSCells) + { + for(U8 sCellIdx = 1; sCellIdx <= RG_SCH_MAX_SCELL ; sCellIdx++) + { +#ifndef PAL_ENABLE_UL_CA + if((ue->cellInfo[sCellIdx] != NULLP) && + (ue->cellInfo[sCellIdx]->sCellState == RG_SCH_SCELL_ACTIVE)) +#else + if(ue->cellInfo[sCellIdx] != NULLP) +#endif + { + cellSch->apisUl->rgSCHUpdBsrShort(ue->cellInfo[sCellIdx]->cell, + ue, ulLcg, bsr); + } + } + } +#endif + + RETVALUE(ROK); +} + +/** + * @brief Truncated BSR update. + * + * @details + * + * Function : rgSCHCmnUpdBsrTrunc + * + * This functions does required updates to handle truncated BSR report. + * + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchLcgCb *ulLcg + * @param[in] U8 bsr + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdBsrTrunc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchLcgCb *ulLcg, +U8 bsr, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnUpdBsrTrunc(cell, ue, ulLcg, bsr, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchLcgCb *ulLcg; +U8 bsr; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnLcg *cmnLcg = NULLP; + S32 cnt; +#ifdef LTE_L2_MEAS + U8 idx; +#endif + + TRC2(rgSCHCmnUpdBsrTrunc); + + if (!RGSCH_LCG_ISCFGD(ulLcg)) + { + err->errCause = RGSCHERR_SCH_LCG_NOT_CFGD; + RETVALUE(RFAILED); + } + /* set all higher prio lcgs bs to 0 and update this lcgs bs and + total bsr= sumofall lcgs bs */ + if (ulLcg->lcgId) + { + for (cnt = ulLcg->lcgId-1; cnt >= 0; cnt--) + { +#ifdef LTE_L2_MEAS + /* If Existing BO is zero the don't do anything */ + if(((RgSchCmnLcg *)(ue->ul.lcgArr[cnt].sch))->bs != 0) + { + for(idx = 0; idx < ue->ul.lcgArr[cnt].numLch; idx++) + { + /* L2_COUNTERS */ + if((ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->ulUeCount) && + (ue->ulActiveLCs & (1 << + (ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->qci -1)))) + { + ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->ulUeCount--; + ue->ulActiveLCs &= ~(1 << + (ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->qci -1)); + } + } + } +#endif + ((RgSchCmnLcg *)(ue->ul.lcgArr[cnt].sch))->bs = 0; + ((RgSchCmnLcg *)(ue->ul.lcgArr[cnt].sch))->reportedBs = 0; + } + } + +#ifdef LTE_L2_MEAS + for (cnt = ulLcg->lcgId; cnt < RGSCH_MAX_LCG_PER_UE; cnt++) + { + if (ulLcg->lcgId == 0) + { + continue; + } + /* If Existing BO is zero the don't do anything */ + if(((RgSchCmnLcg *)(ue->ul.lcgArr[cnt].sch))->bs == 0) + { + for(idx = 0; idx < ue->ul.lcgArr[cnt].numLch; idx++) + { + /* L2_COUNTERS */ + if (!(ue->ulActiveLCs & (1 << + (ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->qci -1)))) + { + ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->ulUeCount++; + ue->ulActiveLCs |= (1 << + (ue->ul.lcgArr[cnt].lcArray[idx]->qciCb->qci -1)); + } + } + } + } +#endif + ue->ul.nonGbrLcgBs = 0; + ue->ul.nonLcg0Bs = 0; + cmnLcg = ((RgSchCmnLcg *)(ulLcg->sch)); + if (TRUE == ue->ul.useExtBSRSizes) + { + cmnLcg->reportedBs = rgSchCmnExtBsrTbl[bsr]; + } + else + { + cmnLcg->reportedBs = rgSchCmnBsrTbl[bsr]; + } + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, cmnLcg->effGbr + cmnLcg->effDeltaMbr); + } + else if(ulLcg->lcgId == 0) + { + /* This is for handeling LCG0 */ + cmnLcg->bs = cmnLcg->reportedBs; + } + else + { + ue->ul.nonGbrLcgBs = RGSCH_MIN(cmnLcg->reportedBs, ue->ul.effAmbr); + cmnLcg->bs = ue->ul.nonGbrLcgBs; + } + ue->ul.totalBsr = cmnLcg->bs; + + for (cnt = ulLcg->lcgId+1; cnt < RGSCH_MAX_LCG_PER_UE; cnt++) + { + /* TODO: The bs for the other LCGs may be stale because some or all of + * the part of bs may have been already scheduled/data received. Please + * consider this when truncated BSR is tested/implemented */ + ue->ul.totalBsr += ((RgSchCmnLcg *)(ue->ul.lcgArr[cnt].sch))->bs; + } + + rgSCHCmnUpdUlCompEffBsr(ue); + +#ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHUpdBsrTrunc(cell, ue, ulLcg, bsr); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHUpdBsrTrunc(cell, ue, ulLcg, bsr); + } + +#ifdef LTE_ADV + if (ue->ul.isUlCaEnabled && ue->numSCells) + { + for(U8 sCellIdx = 1; sCellIdx <= RG_SCH_MAX_SCELL ; sCellIdx++) + { +#ifndef PAL_ENABLE_UL_CA + if((ue->cellInfo[sCellIdx] != NULLP) && + (ue->cellInfo[sCellIdx]->sCellState == RG_SCH_SCELL_ACTIVE)) +#else + if(ue->cellInfo[sCellIdx] != NULLP) +#endif + { + cellSch->apisUl->rgSCHUpdBsrTrunc(ue->cellInfo[sCellIdx]->cell, ue, ulLcg, bsr); + } + } + } +#endif + + RETVALUE(ROK); +} + +/** + * @brief Long BSR update. + * + * @details + * + * Function : rgSCHCmnUpdBsrLong + * + * - Update BSRs for all configured LCGs. + * - Update priority of LCGs if needed. + * - Update UE's position within/across uplink scheduling queues. + * + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 bsArr[] + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdBsrLong +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 *bsArr, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnUpdBsrLong(cell, ue, bsArr, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 *bsArr; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U32 tmpBsArr[4] = {0, 0, 0, 0}; + U32 nonGbrBs = 0; +#ifdef LTE_L2_MEAS + U8 idx1; + U8 idx2; +#endif + U32 lcgId; + + TRC2(rgSCHCmnUpdBsrLong); + +#ifdef LTE_L2_MEAS + for(idx1 = 1; idx1 < RGSCH_MAX_LCG_PER_UE; idx1++) + { + /* If Old BO is non zero then do nothing */ + if ((((RgSchCmnLcg *)(ue->ul.lcgArr[idx1].sch))->bs == 0) + && bsArr[idx1] ) + { + for(idx2 = 0; idx2 < ue->ul.lcgArr[idx1].numLch; idx2++) + { + /* L2_COUNTERS */ + if (!(ue->ulActiveLCs & (1 << + (ue->ul.lcgArr[idx1].lcArray[idx2]->qciCb->qci -1)))) + { + ue->ul.lcgArr[idx1].lcArray[idx2]->qciCb->ulUeCount++; + ue->ulActiveLCs |= (1 << + (ue->ul.lcgArr[idx1].lcArray[idx2]->qciCb->qci -1)); + } + } + } + } +#endif + ue->ul.nonGbrLcgBs = 0; + ue->ul.nonLcg0Bs = 0; + + if (RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[0])) + { + if (TRUE == ue->ul.useExtBSRSizes) + { + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs = rgSchCmnExtBsrTbl[bsArr[0]]; + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->reportedBs = rgSchCmnExtBsrTbl[bsArr[0]]; + tmpBsArr[0] = rgSchCmnExtBsrTbl[bsArr[0]]; + } + else + { + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs = rgSchCmnBsrTbl[bsArr[0]]; + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->reportedBs = rgSchCmnBsrTbl[bsArr[0]]; + tmpBsArr[0] = rgSchCmnBsrTbl[bsArr[0]]; + } + } + for (lcgId = 1; lcgId < RGSCH_MAX_LCG_PER_UE; lcgId++) + { + if (RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[lcgId])) + { + RgSchCmnLcg *cmnLcg = ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgId].sch)); + + if (TRUE == ue->ul.useExtBSRSizes) + { + cmnLcg->reportedBs = rgSchCmnExtBsrTbl[bsArr[lcgId]]; + } + else + { + cmnLcg->reportedBs = rgSchCmnBsrTbl[bsArr[lcgId]]; + } + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, cmnLcg->effGbr + cmnLcg->effDeltaMbr); + tmpBsArr[lcgId] = cmnLcg->bs; + } + else + { + nonGbrBs += cmnLcg->reportedBs; + tmpBsArr[lcgId] = cmnLcg->reportedBs; + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs,ue->ul.effAmbr); + } + } + } + ue->ul.nonGbrLcgBs = RGSCH_MIN(nonGbrBs,ue->ul.effAmbr); + + ue->ul.totalBsr = tmpBsArr[0] + tmpBsArr[1] + tmpBsArr[2] + tmpBsArr[3]; +#ifdef RGR_V1 + if ((ue->bsrTmr.tmrEvnt != TMR_NONE) && (ue->ul.totalBsr == 0)) + { + rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue); + } +#endif + +#ifdef LTEMAC_SPS + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) /* SPS_FIX */ + { + if(ue->ul.totalBsr - tmpBsArr[1] == 0) + {/* Updaing the BSR to SPS only if LCG1 BS is present in sps active state */ + rgSCHCmnSpsBsrRpt(cell, ue, &ue->ul.lcgArr[1]); + } + } +#endif + rgSCHCmnUpdUlCompEffBsr(ue); + +#ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHUpdBsrLong(cell, ue, bsArr); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHUpdBsrLong(cell, ue, bsArr); + } + +#ifdef LTE_ADV + if (ue->ul.isUlCaEnabled && ue->numSCells) + { + for(U8 idx = 1; idx <= RG_SCH_MAX_SCELL ; idx++) + { +#ifndef PAL_ENABLE_UL_CA + if((ue->cellInfo[idx] != NULLP) && + (ue->cellInfo[idx]->sCellState == RG_SCH_SCELL_ACTIVE)) +#else + if(ue->cellInfo[idx] != NULLP) +#endif + { + cellSch->apisUl->rgSCHUpdBsrLong(ue->cellInfo[idx]->cell, ue, bsArr); + } + } + } +#endif + + RETVALUE(ROK); +} + +/** + * @brief PHR update. + * + * @details + * + * Function : rgSCHCmnUpdExtPhr + * + * Updates extended power headroom information for an UE. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 phr + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdExtPhr +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgInfExtPhrCEInfo *extPhr, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnUpdExtPhr(cell, ue, extPhr, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgInfExtPhrCEInfo *extPhr; +RgSchErrInfo *err; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + RgSchCmnAllocRecord *allRcd; + CmLList *node = ueUl->ulAllocLst.last; + +#ifdef LTEMAC_SPS + RgSchCmnUlUeSpsInfo *ulSpsUe = RG_SCH_CMN_GET_UL_SPS_UE(ue,cell); +#endif + TRC2(rgSCHCmnUpdExtPhr); + + UNUSED(err); + + while (node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + node = node->prev; + if (RGSCH_TIMEINFO_SAME(ue->macCeRptTime, allRcd->allocTime)) + { + rgSCHPwrUpdExtPhr(cell, ue, extPhr, allRcd); + break; + } + } +#ifdef LTEMAC_SPS + if(ulSpsUe->isUlSpsActv) + { + rgSCHCmnSpsPhrInd(cell,ue); + } +#endif + + RETVALUE(ROK); +} /* rgSCHCmnUpdExtPhr */ + + + + +/** + * @brief PHR update. + * + * @details + * + * Function : rgSCHCmnUpdPhr + * + * Updates power headroom information for an UE. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 phr + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnUpdPhr +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 phr, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnUpdPhr(cell, ue, phr, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 phr; +RgSchErrInfo *err; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + RgSchCmnAllocRecord *allRcd; + CmLList *node = ueUl->ulAllocLst.last; + +#ifdef LTEMAC_SPS + RgSchCmnUlUeSpsInfo *ulSpsUe = RG_SCH_CMN_GET_UL_SPS_UE(ue,cell); +#endif + TRC2(rgSCHCmnUpdPhr); + + UNUSED(err); + + while (node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + node = node->prev; + if (RGSCH_TIMEINFO_SAME(ue->macCeRptTime, allRcd->allocTime)) + { + rgSCHPwrUpdPhr(cell, ue, phr, allRcd, RG_SCH_CMN_PWR_USE_CFG_MAX_PWR); + break; + } + } +#ifdef LTEMAC_SPS + if(ulSpsUe->isUlSpsActv) + { + rgSCHCmnSpsPhrInd(cell,ue); + } +#endif + + RETVALUE(ROK); +} /* rgSCHCmnUpdPhr */ + +/** + * @brief UL grant for contention resolution. + * + * @details + * + * Function : rgSCHCmnContResUlGrant + * + * Add UE to another queue specifically for CRNTI based contention + * resolution. + * + * + * @param[in] RgSchUeCb *ue + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnContResUlGrant +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnContResUlGrant(cell, ue, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnContResUlGrant); + + #ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHContResUlGrant(cell, ue); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHContResUlGrant(cell, ue); + } + RETVALUE(ROK); +} + +/** + * @brief SR reception handling. + * + * @details + * + * Function : rgSCHCmnSrRcvd + * + * - Update UE's position within/across uplink scheduling queues + * - Update priority of LCGs if needed. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] CmLteTimingInfo frm + * @param[out] RgSchErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnSrRcvd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteTimingInfo frm, +RgSchErrInfo *err +) +#else +PUBLIC S16 rgSCHCmnSrRcvd(cell, ue, frm, err) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteTimingInfo frm; +RgSchErrInfo *err; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + CmLList *node = ueUl->ulAllocLst.last; + + TRC2(rgSCHCmnSrRcvd); + +#ifdef EMTC_ENABLE + emtcStatsUlTomSrInd++; +#endif + + RGSCH_INCR_SUB_FRAME(frm, 1); /* 1 TTI after the time SR was sent */ + while (node) + { + RgSchCmnAllocRecord *allRcd = (RgSchCmnAllocRecord *)node->node; + if (RGSCH_TIMEINFO_SAME(frm, allRcd->allocTime)) + { + break; + } + node = node->prev; + } + //TODO_SID Need to check when it is getting triggered + ue->isSrGrant = TRUE; +#ifdef EMTC_ENABLE + if(cell->emtcEnable) + { + if(ue->isEmtcUe) + { + cellSch->apisEmtcUl->rgSCHSrRcvd(cell, ue); + RETVALUE(ROK); + } + } + else +#endif + { + cellSch->apisUl->rgSCHSrRcvd(cell, ue); + } + RETVALUE(ROK); +} + +/** + * @brief Returns first uplink allocation to send reception + * request to PHY. + * + * @details + * + * Function: rgSCHCmnFirstRcptnReq(cell) + * Purpose: This function returns the first uplink allocation + * (or NULLP if there is none) in the subframe + * in which is expected to prepare and send reception + * request to PHY. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @return RgSchUlAlloc* + **/ +#ifdef ANSI +PUBLIC RgSchUlAlloc *rgSCHCmnFirstRcptnReq +( +RgSchCellCb *cell +) +#else +PUBLIC RgSchUlAlloc *rgSCHCmnFirstRcptnReq(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); +/* ACC_TDD */ + RgSchUlAlloc* alloc = NULLP; + + TRC2(rgSCHCmnFirstRcptnReq); + + if (cellUl->rcpReqIdx != RGSCH_INVALID_INFO) + { + RgSchUlSf* sf = &cellUl->ulSfArr[cellUl->rcpReqIdx]; + alloc = rgSCHUtlUlAllocFirst(sf); + + if (alloc && alloc->hqProc == NULLP) + { + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + } + } + + RETVALUE(alloc); +} + +/** + * @brief Returns first uplink allocation to send reception + * request to PHY. + * + * @details + * + * Function: rgSCHCmnNextRcptnReq(cell) + * Purpose: This function returns the next uplink allocation + * (or NULLP if there is none) in the subframe + * in which is expected to prepare and send reception + * request to PHY. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @return RgSchUlAlloc* + **/ +#ifdef ANSI +PUBLIC RgSchUlAlloc *rgSCHCmnNextRcptnReq +( +RgSchCellCb *cell, +RgSchUlAlloc *alloc +) +#else +PUBLIC RgSchUlAlloc *rgSCHCmnNextRcptnReq(cell, alloc) +RgSchCellCb *cell; +RgSchUlAlloc *alloc; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); +/* ACC-TDD */ + //RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->rcpReqIdx]; + + TRC2(rgSCHCmnNextRcptnReq); +/* ACC-TDD */ + if (cellUl->rcpReqIdx != RGSCH_INVALID_INFO) + { + RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->rcpReqIdx]; + + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + if (alloc && alloc->hqProc == NULLP) + { + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + } + } + else + { + alloc = NULLP; + } + + RETVALUE(alloc); +} +/** + * @brief Collates DRX enabled UE's scheduled in this SF + * + * @details + * + * Function: rgSCHCmnDrxStrtInActvTmrInUl(cell) + * Purpose: This function collates the link + * of UE's scheduled in this SF who + * have drx enabled. It then calls + * DRX specific function to start/restart + * inactivity timer in Ul + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDrxStrtInActvTmrInUl +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnDrxStrtInActvTmrInUl(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchUlSf *sf = &(cellUl->ulSfArr[cellUl->schdIdx]); + RgSchUlAlloc *alloc = rgSCHUtlUlAllocFirst(sf); + CmLListCp ulUeLst; + RgSchUeCb *ueCb; + + + TRC2(rgSCHCmnDrxStrtInActvTmrInUl); + + cmLListInit(&ulUeLst); + + while(alloc) + { + ueCb = alloc->ue; + + if (ueCb) + { + if (!(alloc->grnt.isRtx) && ueCb->isDrxEnabled && !(ueCb->isSrGrant) +#ifdef LTEMAC_SPS + /* ccpu00139513- DRX inactivity timer should not be started for + * UL SPS occasions */ + && (alloc->hqProc->isSpsOccnHqP == FALSE) +#endif + ) + { + cmLListAdd2Tail(&ulUeLst,&(ueCb->ulDrxInactvTmrLnk)); + ueCb->ulDrxInactvTmrLnk.node = (PTR)ueCb; + } + } + + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + }/*while(alloc)*/ + + (Void)rgSCHDrxStrtInActvTmr(cell,&ulUeLst,RG_SCH_DRX_UL); + + RETVOID; +} + + +/** + * @brief Returns first uplink allocation to send HARQ feedback + * request to PHY. + * + * @details + * + * Function: rgSCHCmnFirstHqFdbkAlloc + * Purpose: This function returns the first uplink allocation + * (or NULLP if there is none) in the subframe + * for which it is expected to prepare and send HARQ + * feedback to PHY. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] U8 idx + * @return RgSchUlAlloc* + **/ +#ifdef ANSI +PUBLIC RgSchUlAlloc *rgSCHCmnFirstHqFdbkAlloc +( +RgSchCellCb *cell, +U8 idx +) +#else +PUBLIC RgSchUlAlloc *rgSCHCmnFirstHqFdbkAlloc(cell, idx) +RgSchCellCb *cell; +U8 idx; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); +/* ACC-TDD */ + RgSchUlAlloc *alloc = NULLP; + + TRC2(rgSCHCmnFirstHqFdbkAlloc); + + if (cellUl->hqFdbkIdx[idx] != RGSCH_INVALID_INFO) + { + RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->hqFdbkIdx[idx]]; + alloc = rgSCHUtlUlAllocFirst(sf); + + while (alloc && (alloc->hqProc == NULLP)) + { + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + } + } + + RETVALUE(alloc); +} + +/** + * @brief Returns next allocation to send HARQ feedback for. + * + * @details + * + * Function: rgSCHCmnNextHqFdbkAlloc(cell) + * Purpose: This function returns the next uplink allocation + * (or NULLP if there is none) in the subframe + * for which HARQ feedback needs to be sent. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @return RgSchUlAlloc* + **/ +#ifdef ANSI +PUBLIC RgSchUlAlloc *rgSCHCmnNextHqFdbkAlloc +( +RgSchCellCb *cell, +RgSchUlAlloc *alloc, +U8 idx +) +#else +PUBLIC RgSchUlAlloc *rgSCHCmnNextHqFdbkAlloc(cell, alloc, idx) +RgSchCellCb *cell; +RgSchUlAlloc *alloc; +U8 idx; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + TRC2(rgSCHCmnNextHqFdbkAlloc); + + if (cellUl->hqFdbkIdx[idx] != RGSCH_INVALID_INFO) + { + RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->hqFdbkIdx[idx]]; + + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + while (alloc && (alloc->hqProc == NULLP)) + { + alloc = rgSCHUtlUlAllocNxt(sf, alloc); + } + } + else + { + alloc = NULLP; + } + RETVALUE(alloc); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlGetITbsFrmIMcs + * + * Desc : Returns the Itbs that is mapped to an Imcs + * for the case of uplink. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUlGetITbsFrmIMcs +( +U8 iMcs +) +#else +PUBLIC U8 rgSCHCmnUlGetITbsFrmIMcs(iMcs) +U8 iMcs; +#endif +{ + TRC2(rgSCHCmnUlGetITbsFrmIMcs); + + RETVALUE(rgUlIMcsTbl[iMcs].iTbs); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlGetIMcsFrmITbs + * + * Desc : Returns the Imcs that is mapped to an Itbs + * for the case of uplink. + * + * Ret : + * + * Notes: For iTbs 19, iMcs is dependant on modulation order. + * Refer to 36.213, Table 8.6.1-1 and 36.306 Table 4.1-2 + * for UE capability information + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUlGetIMcsFrmITbs +( +U8 iTbs, +CmLteUeCategory ueCtg +) +#else +PUBLIC U8 rgSCHCmnUlGetIMcsFrmITbs(iTbs, ueCtg) +U8 iTbs; +CmLteUeCategory ueCtg; +#endif +{ + U8 iMcs; + TRC2(rgSCHCmnUlGetIMcsFrmITbs); + + if (iTbs <= 10) + { + iMcs = iTbs; + } + /*a higher layer can force a 64QAM UE to transmit at 16QAM. + * We currently do not support this. Once the support for such + * is added, ueCtg should be replaced by current transmit + * modulation configuration.Refer to 36.213 -8.6.1 + */ + else if ( iTbs < 19 ) + { + iMcs = iTbs + 1; + } + else if ((iTbs == 19) && (ueCtg != CM_LTE_UE_CAT_5)) + { + iMcs = iTbs + 1; + } + else + { + iMcs = iTbs + 2; + } + +#ifdef LTE_TDD + /* This is a Temp fix, done for TENBPLUS-3898, ULSCH SDU corruption + was seen when IMCS exceeds 20 on T2k TDD*/ + if (iMcs > 20) + { + iMcs = 20; + } +#endif + + RETVALUE(iMcs); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlMinTbBitsForITbs + * + * Desc : Returns the minimum number of bits that can + * be given as grant for a specific CQI. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC U32 rgSCHCmnUlMinTbBitsForITbs +( +RgSchCmnUlCell *cellUl, +U8 iTbs +) +#else +PUBLIC U32 rgSCHCmnUlMinTbBitsForITbs(cellUl, iTbs) +RgSchCmnUlCell *cellUl; +U8 iTbs; +#endif +{ + TRC2(rgSCHCmnUlMinTbBitsForITbs); + + RGSCH_ARRAY_BOUND_CHECK(0, rgTbSzTbl[0], iTbs); + + RETVALUE(rgTbSzTbl[0][iTbs][cellUl->sbSize-1]); +} + +/*********************************************************** + * + * Func : rgSCHCmnUlSbAlloc + * + * Desc : Given a required 'number of subbands' and a hole, + * returns a suitable alloc such that the subband + * allocation size is valid + * + * Ret : + * + * Notes: Does not assume either passed numSb or hole size + * to be valid for allocation, and hence arrives at + * an acceptable value. + * File : + * + **********************************************************/ +#ifdef ANSI +PUBLIC RgSchUlAlloc *rgSCHCmnUlSbAlloc +( +RgSchUlSf *sf, +U8 numSb, +RgSchUlHole *hole +) +#else +PUBLIC RgSchUlAlloc *rgSCHCmnUlSbAlloc(sf, numSb, hole) +RgSchUlSf *sf; +U8 numSb; +RgSchUlHole *hole; +#endif +{ + U8 holeSz; /* valid hole size */ + RgSchUlAlloc *alloc; + TRC2(rgSCHCmnUlSbAlloc); + + if ((holeSz = rgSchCmnMult235Tbl[hole->num].prvMatch) == hole->num) + { + numSb = rgSchCmnMult235Tbl[numSb].match; + if (numSb >= holeSz) + { + alloc = rgSCHUtlUlAllocGetCompHole(sf, hole); + } + else + { + alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole); + } + } + else + { + if (numSb < holeSz) + { + numSb = rgSchCmnMult235Tbl[numSb].match; + } + else + { + numSb = rgSchCmnMult235Tbl[numSb].prvMatch; + } + + if ( numSb >= holeSz ) + { + numSb = holeSz; + } + alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole); + } + RETVALUE(alloc); +} + +/** + * @brief To fill the RgSchCmnUeUlAlloc structure of UeCb. + * + * @details + * + * Function: rgSCHCmnUlUeFillAllocInfo + * Purpose: Specific scheduler to call this API to fill the alloc + * information. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlUeFillAllocInfo +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlUeFillAllocInfo(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnUeUlAlloc *ulAllocInfo; + RgSchCmnUlUe *ueUl; + + TRC2(rgSCHCmnUlUeFillAllocInfo); + + ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + ulAllocInfo = &ueUl->alloc; + + /* Fill alloc structure */ + rgSCHCmnUlAllocFillTpc(cell, ue, ulAllocInfo->alloc); + rgSCHCmnUlAllocFillNdmrs(cellUl, ulAllocInfo->alloc); + rgSCHCmnUlAllocLnkHqProc(ue, ulAllocInfo->alloc, ulAllocInfo->alloc->hqProc, + ulAllocInfo->alloc->hqProc->isRetx); + /* Fill PDCCH */ + rgSCHCmnUlFillPdcchWithAlloc(ulAllocInfo->alloc->pdcch, + ulAllocInfo->alloc, ue); + /* Recording information about this allocation */ + rgSCHCmnUlRecordUeAlloc(cell, ue); + + /* Update the UE's outstanding allocation */ + if (!ulAllocInfo->alloc->hqProc->isRetx) + { + rgSCHCmnUlUpdOutStndAlloc(cell, ue, ulAllocInfo->allocdBytes); + } + + RETVOID; +} + +/** + * @brief Update the UEs outstanding alloc based on the BSR report's timing. + * + * + * @details + * + * Function: rgSCHCmnUpdUlCompEffBsr + * Purpose: Clear off all the allocations from outstanding allocation that + * are later than or equal to BSR timing information (stored in UEs datIndTime). + * + * Invoked by: Scheduler + * + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdUlCompEffBsr +( +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnUpdUlCompEffBsr(ue) +RgSchUeCb *ue; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,ue->cell); + CmLList *node = ueUl->ulAllocLst.last; + RgSchCmnAllocRecord *allRcd; + U32 outStndAlloc=0; + U32 nonLcg0OutStndAllocBs=0; + U32 nonLcg0Bsr=0; + U8 lcgId; + RgSchCmnLcg *cmnLcg = NULLP; + TRC2(rgSCHCmnUpdUlCompEffBsr); + + while (node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + if (RGSCH_TIMEINFO_SAME(ue->macCeRptTime, allRcd->allocTime)) + { + node = node->next; + break; + } + node = node->prev; + } + while (node) + { + allRcd = (RgSchCmnAllocRecord *)node->node; + node = node->next; + outStndAlloc += allRcd->alloc; + } + + cmnLcg = (RgSchCmnLcg *)(ue->ul.lcgArr[0].sch); + /* Update UEs LCG0's bs according to the total outstanding BSR allocation.*/ + if (cmnLcg->bs > outStndAlloc) + { + cmnLcg->bs -= outStndAlloc; + ue->ul.minReqBytes = cmnLcg->bs; + outStndAlloc = 0; + } + else + { + nonLcg0OutStndAllocBs = outStndAlloc - cmnLcg->bs; + cmnLcg->bs = 0; + } + + for(lcgId = 1;lcgId < RGSCH_MAX_LCG_PER_UE; lcgId++) + { + if(RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[lcgId])) + { + cmnLcg = ((RgSchCmnLcg *) (ue->ul.lcgArr[lcgId].sch)); + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + nonLcg0Bsr += cmnLcg->bs; + } + } + } + nonLcg0Bsr += ue->ul.nonGbrLcgBs; + if (nonLcg0OutStndAllocBs > nonLcg0Bsr) + { + nonLcg0Bsr = 0; + } + else + { + nonLcg0Bsr -= nonLcg0OutStndAllocBs; + } + ue->ul.nonLcg0Bs = nonLcg0Bsr; + /* Cap effBsr with nonLcg0Bsr and append lcg0 bs. + * nonLcg0Bsr limit applies only to lcg1,2,3 */ + /* better be handled in individual scheduler */ + ue->ul.effBsr = nonLcg0Bsr +\ + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs; + RETVOID; +} + +/** + * @brief Records information about the current allocation. + * + * @details + * + * Function: rgSCHCmnUlRecordUeAlloc + * Purpose: Records information about the curent allocation. + * This includes the allocated bytes, as well + * as some power information. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlRecordUeAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnUlRecordUeAlloc(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ +#ifdef LTE_TDD + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); +#endif + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + CmLListCp *lst = &ueUl->ulAllocLst; + CmLList *node = ueUl->ulAllocLst.first; + RgSchCmnAllocRecord *allRcd = (RgSchCmnAllocRecord *)(node->node); + RgSchCmnUeUlAlloc *ulAllocInfo = &ueUl->alloc; + CmLteUeCategory ueCtg = (CmLteUeCategory)(RG_SCH_CMN_GET_UE_CTGY(ue)); + TRC2(rgSCHCmnUlRecordUeAlloc); + + cmLListDelFrm(lst, &allRcd->lnk); +#ifndef LTE_TDD + /* To the crntTime, add the MIN time at which UE will + * actually send the BSR i.e DELTA+4 */ + allRcd->allocTime = cell->crntTime; + /*ccpu00116293 - Correcting relation between UL subframe and DL subframe based on RG_UL_DELTA*/ +#ifdef EMTC_ENABLE + if(ue->isEmtcUe == TRUE) + { + RGSCH_INCR_SUB_FRAME_EMTC(allRcd->allocTime, + (TFU_ULCNTRL_DLDELTA + RGSCH_PDCCH_PUSCH_DELTA)); + } + else +#endif + { + RGSCH_INCR_SUB_FRAME(allRcd->allocTime, + (TFU_ULCNTRL_DLDELTA + RGSCH_PDCCH_PUSCH_DELTA)); + } +#else + allRcd->allocTime = cellUl->schdTime; +#endif + cmLListAdd2Tail(lst, &allRcd->lnk); + + /* Filling in the parameters to be recorded */ + allRcd->alloc = ulAllocInfo->allocdBytes; + //allRcd->numRb = ulAllocInfo->alloc->grnt.numRb; + allRcd->numRb = (ulAllocInfo->alloc->grnt.numVrbg * MAX_5GTF_VRBG_SIZE); + /*Recording the UL CQI derived from the maxUlCqi */ + allRcd->cqi = rgSCHCmnUlGetCqi(cell, ue, ueCtg); + allRcd->tpc = ulAllocInfo->alloc->grnt.tpc; + + rgSCHPwrRecordRbAlloc(cell, ue, allRcd->numRb); + + cell->measurements.ulBytesCnt += ulAllocInfo->allocdBytes; + + RETVOID; +} + +/** PHR handling for MSG3 + * @brief Records allocation information of msg3 in the the UE. + * + * @details + * + * Function: rgSCHCmnUlRecMsg3Alloc + * Purpose: Records information about msg3 allocation. + * This includes the allocated bytes, as well + * as some power information. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchRaCb *raCb + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlRecMsg3Alloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchRaCb *raCb +) +#else +PUBLIC Void rgSCHCmnUlRecMsg3Alloc(cell, ue, raCb) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchRaCb *raCb; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + CmLListCp *lst = &ueUl->ulAllocLst; + CmLList *node = ueUl->ulAllocLst.first; + RgSchCmnAllocRecord *allRcd = (RgSchCmnAllocRecord *)(node->node); + + /* Stack Crash problem for TRACE5 changes */ + TRC2(rgSCHCmnUlRecMsg3Alloc); + + cmLListDelFrm(lst, node); + allRcd->allocTime = raCb->msg3AllocTime; + cmLListAdd2Tail(lst, node); + + /* Filling in the parameters to be recorded */ + allRcd->alloc = raCb->msg3Grnt.datSz; + allRcd->numRb = raCb->msg3Grnt.numRb; + allRcd->cqi = raCb->ccchCqi; + allRcd->tpc = raCb->msg3Grnt.tpc; + + rgSCHPwrRecordRbAlloc(cell, ue, allRcd->numRb); + + RETVOID; +} +/** + * @brief Keeps track of the most recent RG_SCH_CMN_MAX_ALLOC_TRACK + * allocations to track. Adds this allocation to the ueUl's ulAllocLst. + * + * + * @details + * + * Function: rgSCHCmnUlUpdOutStndAlloc + * Purpose: Recent Allocation shall be at First Pos'n. + * Remove the last node, update the fields + * with the new allocation and add at front. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U32 alloc + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlUpdOutStndAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U32 alloc +) +#else +PUBLIC Void rgSCHCmnUlUpdOutStndAlloc(cell, ue, alloc) +RgSchCellCb *cell; +RgSchUeCb *ue; +U32 alloc; +#endif +{ + U32 nonLcg0Alloc=0; + TRC2(rgSCHCmnUlUpdOutStndAlloc); + + /* Update UEs LCG0's bs according to the total outstanding BSR allocation.*/ + if (((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs > alloc) + { + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs -= alloc; + } + else + { + nonLcg0Alloc = alloc - ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs; + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs = 0; + } + + if (nonLcg0Alloc >= ue->ul.nonLcg0Bs) + { + ue->ul.nonLcg0Bs = 0; + } + else + { + ue->ul.nonLcg0Bs -= nonLcg0Alloc; + } + /* Cap effBsr with effAmbr and append lcg0 bs. + * effAmbr limit applies only to lcg1,2,3 non GBR LCG's*/ + /* better be handled in individual scheduler */ + ue->ul.effBsr = ue->ul.nonLcg0Bs +\ + ((RgSchCmnLcg *)(ue->ul.lcgArr[0].sch))->bs; +#ifdef RGR_V1 + if (ue->ul.effBsr == 0) + { + if (ue->bsrTmr.tmrEvnt != TMR_NONE) + { + rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue); + } + /* ccpu00133008 */ + if (FALSE == ue->isSrGrant) + { + if (ue->ul.bsrTmrCfg.isPrdBsrTmrPres) + { + /* + rgSCHTmrStartTmr(cell, ue, RG_SCH_TMR_BSR, + ue->ul.bsrTmrCfg.prdBsrTmr); + */ + } + } + } +#endif + /* Resetting UEs lower Cap */ + ue->ul.minReqBytes = 0; + + RETVOID; +} + + +/** + * @brief Returns the "Itbs" for a given UE. + * + * @details + * + * Function: rgSCHCmnUlGetITbs + * Purpose: This function returns the "Itbs" for a given UE. + * + * Invoked by: Scheduler + * + * @param[in] RgSchUeCb *ue + * @return U8 + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUlGetITbs +( +RgSchCellCb *cell, +RgSchUeCb *ue, +Bool isEcp +) +#else +PUBLIC U8 rgSCHCmnUlGetITbs(cell, ue, isEcp) +RgSchCellCb *cell; +RgSchUeCb *ue; +Bool isEcp; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + /* CQI will be capped to maxUlCqi for 16qam UEs */ + CmLteUeCategory ueCtgy = (CmLteUeCategory)(RG_SCH_CMN_GET_UE_CTGY(ue)); + U8 cqi; +#ifdef UL_LA + S32 iTbs; + U8 maxiTbs = rgSchCmnUlCqiToTbsTbl[(U8)isEcp][ueUl->maxUlCqi]; +#endif + + TRC2(rgSCHCmnUlGetITbs); + + /* #ifdef RG_SCH_CMN_EXT_CP_SUP For ECP pick index 1 */ +#ifdef TFU_UPGRADE + if ( (ueCtgy != CM_LTE_UE_CAT_5) && + (ueUl->validUlCqi > ueUl->maxUlCqi) + ) + { + cqi = ueUl->maxUlCqi; + } + else + { + cqi = ueUl->validUlCqi; + } + +#ifdef UL_LA + iTbs = (ueUl->ulLaCb.cqiBasediTbs + ueUl->ulLaCb.deltaiTbs)/100; + + RG_SCH_CHK_ITBS_RANGE(iTbs, maxiTbs); + + iTbs = RGSCH_MIN(iTbs, ue->cell->thresholds.maxUlItbs); + +#ifdef LTE_TDD + /* This is a Temp fix, done for TENBPLUS-3898, ULSCH SDU corruption + was seen when IMCS exceeds 20 on T2k TDD */ + if (iTbs > 19) + { + iTbs = 19; + } +#endif + RETVALUE(iTbs); +#endif +#else + if ( (ueCtgy != CM_LTE_UE_CAT_5) && (ueUl->crntUlCqi[0] > ueUl->maxUlCqi )) + { + cqi = ueUl->maxUlCqi; + } + else + { + cqi = ueUl->crntUlCqi[0]; + } +#endif + RETVALUE(rgSchCmnUlCqiToTbsTbl[(U8)isEcp][cqi]); +} + +/** + * @brief This function adds the UE to DLRbAllocInfo TX lst. + * + * @details + * + * Function: rgSCHCmnDlRbInfoAddUeTx + * Purpose: This function adds the UE to DLRbAllocInfo TX lst. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRbInfoAddUeTx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +) +#else +PRIVATE Void rgSCHCmnDlRbInfoAddUeTx(cell, allocInfo, ue, hqP) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnDlRbInfoAddUeTx); + + if (hqP->reqLnk.node == NULLP) + { + if (cellSch->dl.isDlFreqSel) + { + cellSch->apisDlfs->rgSCHDlfsAddUeToLst(cell, + &allocInfo->dedAlloc.txHqPLst, hqP); + } + else + { + { + cmLListAdd2Tail(&allocInfo->dedAlloc.txHqPLst, &hqP->reqLnk); + } + hqP->reqLnk.node = (PTR)hqP; + } + } + RETVOID; +} + +/** + * @brief This function adds the UE to DLRbAllocInfo RETX lst. + * + * @details + * + * Function: rgSCHCmnDlRbInfoAddUeRetx + * Purpose: This function adds the UE to DLRbAllocInfo RETX lst. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRbInfoAddUeRetx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +) +#else +PRIVATE Void rgSCHCmnDlRbInfoAddUeRetx(cell, allocInfo, ue, hqP) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(ue->cell); + + TRC2(rgSCHCmnDlRbInfoAddUeRetx); + + if (cellSch->dl.isDlFreqSel) + { + cellSch->apisDlfs->rgSCHDlfsAddUeToLst(cell, + &allocInfo->dedAlloc.retxHqPLst, hqP); + } + else + { + /* checking UE's presence in this lst is unnecessary */ + cmLListAdd2Tail(&allocInfo->dedAlloc.retxHqPLst, &hqP->reqLnk); + hqP->reqLnk.node = (PTR)hqP; + } + RETVOID; +} + +/** + * @brief This function adds the UE to DLRbAllocInfo TX-RETX lst. + * + * @details + * + * Function: rgSCHCmnDlRbInfoAddUeRetxTx + * Purpose: This adds the UE to DLRbAllocInfo TX-RETX lst. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRbInfoAddUeRetxTx +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +) +#else +PRIVATE Void rgSCHCmnDlRbInfoAddUeRetxTx(allocInfo, ue, hqP) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +RgSchDlHqProcCb *hqP; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(ue->cell); + + TRC2(rgSCHCmnDlRbInfoAddUeRetxTx); + + if (cellSch->dl.isDlFreqSel) + { + cellSch->apisDlfs->rgSCHDlfsAddUeToLst(cell, + &allocInfo->dedAlloc.txRetxHqPLst, hqP); + } + else + { + cmLListAdd2Tail(&allocInfo->dedAlloc.txRetxHqPLst, &hqP->reqLnk); + hqP->reqLnk.node = (PTR)hqP; + } + RETVOID; +} + +/** + * @brief This function adds the UE to DLRbAllocInfo NonSchdRetxLst. + * + * @details + * + * Function: rgSCHCmnDlAdd2NonSchdRetxLst + * Purpose: During RB estimation for RETX, if allocation fails + * then appending it to NonSchdRetxLst, the further + * action is taken as part of Finalization in + * respective schedulers. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAdd2NonSchdRetxLst +( +RgSchCmnDlRbAllocInfo *allocInfo, +RgSchUeCb *ue, +RgSchDlHqProcCb *hqP +) +#else +PRIVATE Void rgSCHCmnDlAdd2NonSchdRetxLst(allocInfo, ue, hqP) +RgSchCmnDlRbAllocInfo *allocInfo; +RgSchUeCb *ue; +RgSchDlHqProcCb *hqP; +#endif +{ + CmLList *schdLnkNode; + + TRC2(rgSCHCmnDlAdd2NonSchdRetxLst); + +#ifdef LTEMAC_SPS + if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) && + (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP))) + { + RETVOID; + } +#endif + + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + cmLListAdd2Tail(&allocInfo->dedAlloc.nonSchdRetxHqPLst, schdLnkNode); + + RETVOID; +} + + + +/** + * @brief This function adds the UE to DLRbAllocInfo NonSchdTxRetxLst. + * + * @details + * + * Function: rgSCHCmnDlAdd2NonSchdTxRetxLst + * Purpose: During RB estimation for TXRETX, if allocation fails + * then appending it to NonSchdTxRetxLst, the further + * action is taken as part of Finalization in + * respective schedulers. + * + * Invoked by: Common Scheduler + * + * @param[out] RgSchCmnDlRbAllocInfo *allocInfo + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef LTE_TDD +/** + * @brief This function handles the initialisation of DL HARQ/ACK feedback + * timing information for eaach DL subframe. + * + * @details + * + * Function: rgSCHCmnDlANFdbkInit + * Purpose: Each DL subframe stores the sfn and subframe + * information of UL subframe in which it expects + * HARQ ACK/NACK feedback for this subframe.It + * generates the information based on Downlink + * Association Set Index table. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlANFdbkInit +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlANFdbkInit(cell) +RgSchCellCb *cell; +#endif +{ + U8 sfCount; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 maxDlSubfrms = cell->numDlSubfrms; + U8 sfNum; + U8 idx; + U8 dlIdx; + U8 calcSfnOffset; + S8 calcSfNum; + U8 ulSfCnt =0; + RgSchTddSubfrmInfo ulSubfrmInfo; + U8 maxUlSubfrms; + + TRC2(rgSCHCmnDlANFdbkInit); + + ulSubfrmInfo = rgSchTddMaxUlSubfrmTbl[ulDlCfgIdx]; + maxUlSubfrms = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + + /* Generate HARQ ACK/NACK feedback information for each DL sf in a radio frame + * Calculate this information based on DL Association set Index table */ + for (sfCount = 0, sfNum = 0; sfCount < maxUlSubfrms; sfCount++) + { + while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] != + RG_SCH_TDD_UL_SUBFRAME) + { + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + ulSfCnt++; + + for(idx=0; idx < rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][sfNum].\ + numFdbkSubfrms; idx++) + { + calcSfNum = sfNum - rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][sfNum].\ + subfrmNum[idx]; + if(calcSfNum < 0) + { + calcSfnOffset = RGSCH_CEIL(-calcSfNum, RGSCH_NUM_SUB_FRAMES); + } + else + { + calcSfnOffset = 0; + } + + calcSfNum = ((RGSCH_NUM_SUB_FRAMES * calcSfnOffset) + calcSfNum)\ + % RGSCH_NUM_SUB_FRAMES; + + if(calcSfNum <= RG_SCH_CMN_SPL_SUBFRM_1) + { + dlIdx = calcSfNum; + } + else if((ulSubfrmInfo.switchPoints == 2) && (calcSfNum <= \ + RG_SCH_CMN_SPL_SUBFRM_6)) + { + dlIdx = calcSfNum - ulSubfrmInfo.numFrmHf1; + } + else + { + dlIdx = calcSfNum - maxUlSubfrms; + } + + cell->subFrms[dlIdx]->dlFdbkInfo.subframe = sfNum; + cell->subFrms[dlIdx]->dlFdbkInfo.sfnOffset = calcSfnOffset; + cell->subFrms[dlIdx]->dlFdbkInfo.m = idx; + } + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + + /* DL subframes in the subsequent radio frames are initialized + * with the previous radio frames */ + for(dlIdx = RGSCH_NUM_SUB_FRAMES - maxUlSubfrms; dlIdx < maxDlSubfrms;\ + dlIdx++) + { + sfNum = dlIdx - rgSchTddNumDlSubfrmTbl[ulDlCfgIdx]\ + [RGSCH_NUM_SUB_FRAMES-1]; + cell->subFrms[dlIdx]->dlFdbkInfo.subframe = \ + cell->subFrms[sfNum]->dlFdbkInfo.subframe; + cell->subFrms[dlIdx]->dlFdbkInfo.sfnOffset = \ + cell->subFrms[sfNum]->dlFdbkInfo.sfnOffset; + cell->subFrms[dlIdx]->dlFdbkInfo.m = cell->subFrms[sfNum]->dlFdbkInfo.m; + } + RETVALUE(ROK); +} + +/** + * @brief This function handles the initialization of uplink association + * set information for each DL subframe. + * + * + * @details + * + * Function: rgSCHCmnDlKdashUlAscInit + * Purpose: Each DL sf stores the sfn and sf information of UL sf + * in which it expects HQ ACK/NACK trans. It generates the information + * based on k` in UL association set index table. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlKdashUlAscInit +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlKdashUlAscInit(cell) +RgSchCellCb *cell; +#endif +{ + U8 sfCount; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 maxDlSubfrms = cell->numDlSubfrms; + U8 sfNum; + U8 dlIdx; + S8 calcSfnOffset; + S8 calcSfNum; + U8 ulSfCnt =0; + RgSchTddSubfrmInfo ulSubfrmInfo = rgSchTddMaxUlSubfrmTbl[ulDlCfgIdx]; + U8 maxUlSubfrms = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx]\ + [RGSCH_NUM_SUB_FRAMES-1]; + U8 dlPres = 0; + + TRC2(rgSCHCmnDlKdashUlAscInit); + + /* Generate ACK/NACK offset information for each DL subframe in a radio frame + * Calculate this information based on K` in UL Association Set table */ + for (sfCount = 0, sfNum = 0; sfCount < maxUlSubfrms; sfCount++) + { + while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] != + RG_SCH_TDD_UL_SUBFRAME) + { + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + ulSfCnt++; + + calcSfNum = (sfNum - rgSchTddUlAscIdxKDashTbl[ulDlCfgIdx-1][sfNum] + \ + RGSCH_NUM_SUB_FRAMES) % RGSCH_NUM_SUB_FRAMES; + calcSfnOffset = sfNum - rgSchTddUlAscIdxKDashTbl[ulDlCfgIdx-1][sfNum]; + if(calcSfnOffset < 0) + { + calcSfnOffset = RGSCH_CEIL(-calcSfnOffset, RGSCH_NUM_SUB_FRAMES); + } + else + { + calcSfnOffset = 0; + } + + if(calcSfNum <= RG_SCH_CMN_SPL_SUBFRM_1) + { + dlIdx = calcSfNum; + } + else if((ulSubfrmInfo.switchPoints == 2) && + (calcSfNum <= RG_SCH_CMN_SPL_SUBFRM_6)) + { + dlIdx = calcSfNum - ulSubfrmInfo.numFrmHf1; + } + else + { + dlIdx = calcSfNum - maxUlSubfrms; + } + + cell->subFrms[dlIdx]->ulAscInfo.subframe = sfNum; + cell->subFrms[dlIdx]->ulAscInfo.sfnOffset = calcSfnOffset; + + /* set dlIdx for which ulAscInfo is updated */ + dlPres = dlPres | (1 << dlIdx); + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + + /* Set Invalid information for which ulAscInfo is not present */ + for (sfCount = 0; + sfCount < rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + sfCount++) + { + /* If dlPres is 0, ulAscInfo is not present in that DL index */ + if(! ((dlPres >> sfCount)&0x01)) + { + cell->subFrms[sfCount]->ulAscInfo.sfnOffset = + RGSCH_INVALID_INFO; + cell->subFrms[sfCount]->ulAscInfo.subframe = + RGSCH_INVALID_INFO; + } + } + + /* DL subframes in the subsequent radio frames are initialized + * with the previous radio frames */ + for(dlIdx = RGSCH_NUM_SUB_FRAMES - maxUlSubfrms; dlIdx < maxDlSubfrms; + dlIdx++) + { + sfNum = dlIdx - \ + rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + cell->subFrms[dlIdx]->ulAscInfo.subframe = + cell->subFrms[sfNum]->ulAscInfo.subframe; + cell->subFrms[dlIdx]->ulAscInfo.sfnOffset = + cell->subFrms[sfNum]->ulAscInfo.sfnOffset; + } + RETVALUE(ROK); +} + + +/** + * @brief This function initialises the 'Np' value for 'p' + * + * @details + * + * Function: rgSCHCmnDlNpValInit + * Purpose: To initialise the 'Np' value for each 'p'. It is used + * to find the mapping between nCCE and 'p' and used in + * HARQ ACK/NACK reception. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlNpValInit +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlNpValInit(cell) +RgSchCellCb *cell; +#endif +{ + U8 idx; + U16 np; + TRC2(rgSCHCmnDlNpValInit); + + /* Always Np is 0 for p=0 */ + cell->rgSchTddNpValTbl[0] = 0; + + for(idx=1; idx < RGSCH_TDD_MAX_P_PLUS_ONE_VAL; idx++) + { + np = cell->bwCfg.dlTotalBw * (idx * RG_SCH_CMN_NUM_SUBCAR - 4); + cell->rgSchTddNpValTbl[idx] = (U8) (np/36); + } + + RETVALUE(ROK); +} + +/** + * @brief This function handles the creation of RACH preamble + * list to queue the preambles and process at the scheduled + * time. + * + * @details + * + * Function: rgSCHCmnDlCreateRachPrmLst + * Purpose: To create RACH preamble list based on RA window size. + * It is used to queue the preambles and process it at the + * scheduled time. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlCreateRachPrmLst +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlCreateRachPrmLst(cell) +RgSchCellCb *cell; +#endif +{ + U8 raArrSz; + S16 ret; + U8 lstSize; + + TRC2(rgSCHCmnDlCreateRachPrmLst); + + RG_SCH_CMN_CALC_RARSPLST_SIZE(cell, raArrSz); + + lstSize = raArrSz * RGSCH_MAX_RA_RNTI_PER_SUBFRM * RGSCH_NUM_SUB_FRAMES; + + cell->raInfo.maxRaSize = raArrSz; + ret = rgSCHUtlAllocSBuf(cell->instIdx, + (Data **)(&cell->raInfo.raReqLst), (Size)(lstSize * sizeof(CmLListCp))); + if (ret != ROK) + { + RETVALUE(ret); + } + + cell->raInfo.lstSize = lstSize; + + RETVALUE(ROK); +} + + +/** + * @brief This function handles the initialization of RACH Response + * information at each DL subframe. + * + * @details + * + * Function: rgSCHCmnDlRachInfoInit + * Purpose: Each DL subframe stores the sfn and subframe information of + * possible RACH response allowed for UL subframes. It generates + * the information based on PRACH configuration. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlRachInfoInit +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlRachInfoInit(cell) +RgSchCellCb *cell; +#endif +{ + U8 sfCount; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 sfNum; + U8 ulSfCnt =0; + U8 maxUlSubfrms = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx]\ + [RGSCH_NUM_SUB_FRAMES-1]; + U8 raArrSz; + RgSchTddRachRspLst rachRspLst[3][RGSCH_NUM_SUB_FRAMES]; + U8 startWin; + U8 endWin; + U8 sfnIdx; + U8 subfrmIdx; + U8 endSubfrmIdx; + U8 startSubfrmIdx; + S16 ret; + RgSchTddRachDelInfo *delInfo; + S8 sfnOffset; + U8 numSubfrms; + + TRC2(rgSCHCmnDlRachInfoInit); + + cmMemset((U8 *)rachRspLst, 0, sizeof(rachRspLst)); + + RG_SCH_CMN_CALC_RARSPLST_SIZE(cell, raArrSz); + + /* Include Special subframes */ + maxUlSubfrms = maxUlSubfrms + \ + rgSchTddMaxUlSubfrmTbl[ulDlCfgIdx].switchPoints; + for (sfCount = 0, sfNum = 0; sfCount < maxUlSubfrms; sfCount++) + { + while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] == + RG_SCH_TDD_DL_SUBFRAME) + { + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + ulSfCnt++; + + startWin = (sfNum + RG_SCH_CMN_RARSP_WAIT_PRD + \ + ((RgSchCmnCell *)cell->sc.sch)->dl.numRaSubFrms); + endWin = (startWin + cell->rachCfg.raWinSize - 1); + startSubfrmIdx = + rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][startWin%RGSCH_NUM_SUB_FRAMES]; + /* Find the next DL subframe starting from Subframe 0 */ + if((startSubfrmIdx % RGSCH_NUM_SUB_FRAMES) == 0) + { + startWin = RGSCH_CEIL(startWin, RGSCH_NUM_SUB_FRAMES); + startWin = startWin * RGSCH_NUM_SUB_FRAMES; + } + + endSubfrmIdx = + rgSchTddLowDlSubfrmIdxTbl[ulDlCfgIdx][endWin%RGSCH_NUM_SUB_FRAMES]; + endWin = (endWin/RGSCH_NUM_SUB_FRAMES) * RGSCH_NUM_SUB_FRAMES \ + + endSubfrmIdx; + if(startWin > endWin) + { + continue; + } + /* Find all the possible RACH Response transmission + * time within the RA window size */ + startSubfrmIdx = startWin%RGSCH_NUM_SUB_FRAMES; + for(sfnIdx = startWin/RGSCH_NUM_SUB_FRAMES; + sfnIdx <= endWin/RGSCH_NUM_SUB_FRAMES; sfnIdx++) + { + if(sfnIdx == endWin/RGSCH_NUM_SUB_FRAMES) + { + endSubfrmIdx = endWin%RGSCH_NUM_SUB_FRAMES; + } + else + { + endSubfrmIdx = RGSCH_NUM_SUB_FRAMES-1; + } + + /* Find all the possible RACH Response transmission + * time within radio frame */ + for(subfrmIdx = startSubfrmIdx; + subfrmIdx <= endSubfrmIdx; subfrmIdx++) + { + if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][subfrmIdx] == + RG_SCH_TDD_UL_SUBFRAME) + { + continue; + } + subfrmIdx = rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][subfrmIdx]; + /* Find the next DL subframe starting from Subframe 0 */ + if(subfrmIdx == RGSCH_NUM_SUB_FRAMES) + { + break; + } + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rachRspLst[sfnIdx], subfrmIdx); + numSubfrms = + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].numSubfrms; + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].sfnOffset = sfnIdx; + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].subframe[numSubfrms] + = sfNum; + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].numSubfrms++; + } + startSubfrmIdx = RG_SCH_CMN_SUBFRM_0; + } + /* Update the subframes to be deleted at this subframe */ + /* Get the subframe after the end of RA window size */ + endWin++; + endSubfrmIdx++; + sfnOffset = endWin/RGSCH_NUM_SUB_FRAMES; + if(sfnOffset < 0) + { + sfnOffset += raArrSz; + } + sfnIdx = (endWin/RGSCH_NUM_SUB_FRAMES) % raArrSz; + + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx],endSubfrmIdx-1); + if((endSubfrmIdx == RGSCH_NUM_SUB_FRAMES) || + (rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][endSubfrmIdx] == + RGSCH_NUM_SUB_FRAMES)) + { + subfrmIdx = + rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][RG_SCH_CMN_SUBFRM_0]; + } + else + { + subfrmIdx = rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][endSubfrmIdx]; + } + + delInfo = &rachRspLst[sfnIdx][subfrmIdx].delInfo; + delInfo->sfnOffset = sfnOffset; + delInfo->subframe[delInfo->numSubfrms] = sfNum; + delInfo->numSubfrms++; + + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + + ret = rgSCHCmnDlCpyRachInfo(cell, rachRspLst, raArrSz); + if (ret != ROK) + { + RETVALUE(ret); + } + + RETVALUE(ROK); +} + +/** + * @brief This function handles the initialization of PHICH information + * for each DL subframe based on PHICH table. + * + * @details + * + * Function: rgSCHCmnDlPhichOffsetInit + * Purpose: Each DL subf stores the sfn and subf information of UL subframe + * for which it trnsmts PHICH in this subframe. It generates the information + * based on PHICH table. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlPhichOffsetInit +( +RgSchCellCb *cell +) +#else +PRIVATE S16 rgSCHCmnDlPhichOffsetInit(cell) +RgSchCellCb *cell; +#endif +{ + U8 sfCount; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 maxDlSubfrms = cell->numDlSubfrms; + U8 sfNum; + U8 dlIdx; + U8 dlPres = 0; + U8 calcSfnOffset; + U8 calcSfNum; + U8 ulSfCnt =0; + RgSchTddSubfrmInfo ulSubfrmInfo = rgSchTddMaxUlSubfrmTbl[ulDlCfgIdx]; + U8 maxUlSubfrms = rgSchTddNumUlSubfrmTbl[ulDlCfgIdx]\ + [RGSCH_NUM_SUB_FRAMES-1]; + + TRC2(rgSCHCmnDlPhichOffsetInit); + + /* Generate PHICH offset information for each DL subframe in a radio frame + * Calculate this information based on K in PHICH table */ + for (sfCount = 0, sfNum = 0; sfCount < maxUlSubfrms; sfCount++) + { + while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] != + RG_SCH_TDD_UL_SUBFRAME) + { + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + ulSfCnt++; + + calcSfNum = (rgSchTddKPhichTbl[ulDlCfgIdx][sfNum] + sfNum) % \ + RGSCH_NUM_SUB_FRAMES; + calcSfnOffset = (rgSchTddKPhichTbl[ulDlCfgIdx][sfNum] + sfNum) / \ + RGSCH_NUM_SUB_FRAMES; + + if(calcSfNum <= RG_SCH_CMN_SPL_SUBFRM_1) + { + dlIdx = calcSfNum; + } + else if((ulSubfrmInfo.switchPoints == 2) && + (calcSfNum <= RG_SCH_CMN_SPL_SUBFRM_6)) + { + dlIdx = calcSfNum - ulSubfrmInfo.numFrmHf1; + } + else + { + dlIdx = calcSfNum - maxUlSubfrms; + } + + cell->subFrms[dlIdx]->phichOffInfo.subframe = sfNum; + cell->subFrms[dlIdx]->phichOffInfo.numSubfrms = 1; + + cell->subFrms[dlIdx]->phichOffInfo.sfnOffset = calcSfnOffset; + + /* set dlIdx for which phich offset is updated */ + dlPres = dlPres | (1 << dlIdx); + sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES; + } + + /* Set Invalid information for which phich offset is not present */ + for (sfCount = 0; + sfCount < rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + sfCount++) + { + /* If dlPres is 0, phich offset is not present in that DL index */ + if(! ((dlPres >> sfCount)&0x01)) + { + cell->subFrms[sfCount]->phichOffInfo.sfnOffset = + RGSCH_INVALID_INFO; + cell->subFrms[sfCount]->phichOffInfo.subframe = + RGSCH_INVALID_INFO; + cell->subFrms[sfCount]->phichOffInfo.numSubfrms = 0; + } + } + + /* DL subframes in the subsequent radio frames are + * initialized with the previous radio frames */ + for(dlIdx = RGSCH_NUM_SUB_FRAMES - maxUlSubfrms; + dlIdx < maxDlSubfrms; dlIdx++) + { + sfNum = dlIdx - \ + rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1]; + + cell->subFrms[dlIdx]->phichOffInfo.subframe = + cell->subFrms[sfNum]->phichOffInfo.subframe; + + cell->subFrms[dlIdx]->phichOffInfo.sfnOffset = + cell->subFrms[sfNum]->phichOffInfo.sfnOffset; + } + RETVALUE(ROK); +} + + +/** + * @brief Updation of Sch vars per TTI. + * + * @details + * + * Function: rgSCHCmnUpdVars + * Purpose: Updation of Sch vars per TTI. + * + * @param[in] RgSchCellCb *cell + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUpdVars +( +RgSchCellCb *cell +) +#else +PUBLIC Void rgSCHCmnUpdVars(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + CmLteTimingInfo timeInfo; + U8 idx; + U8 ulSubframe; + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 msg3Subfrm; + U8 Mval; + TRC2(rgSCHCmnUpdVars); + + /* ccpu00132654-ADD- Initializing all the indices in every subframe*/ + rgSCHCmnInitVars(cell); + + idx = (cell->crntTime.subframe + TFU_ULCNTRL_DLDELTA) % RGSCH_NUM_SUB_FRAMES; + /* Calculate the UL scheduling subframe idx based on the + Pusch k table */ + if(rgSchTddPuschTxKTbl[ulDlCfgIdx][idx] != 0) + { + /* PUSCH transmission is based on offset from DL + * PDCCH scheduling */ + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo, TFU_ULCNTRL_DLDELTA); + ulSubframe = rgSchTddPuschTxKTbl[ulDlCfgIdx][timeInfo.subframe]; + /* Add the DCI-0 to PUSCH time to get the time of UL subframe */ + RGSCHCMNADDTOCRNTTIME(timeInfo, timeInfo, ulSubframe); +#ifdef LTEMAC_SPS + cellUl->schdTti = timeInfo.sfn * 10 + timeInfo.subframe; +#endif + /* Fetch the corresponding UL subframe Idx in UL sf array */ + cellUl->schdIdx = rgSCHCmnGetUlSfIdx(&timeInfo, cell); + /* Fetch the corresponding UL Harq Proc ID */ + cellUl->schdHqProcIdx = rgSCHCmnGetUlHqProcIdx(&timeInfo, cell); + cellUl->schdTime = timeInfo; + } + Mval = rgSchTddPhichMValTbl[ulDlCfgIdx][idx]; + if(Mval) + { + /* Fetch the tx time for DL HIDCI-0 */ + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo, TFU_ULCNTRL_DLDELTA); + /* Fetch the corresponding n-k tx time of PUSCH */ + cellUl->hqFdbkIdx[0] = rgSCHCmnGetPhichUlSfIdx(&timeInfo, cell); + /* Retx will happen according to the Pusch k table */ + cellUl->reTxIdx[0] = cellUl->schdIdx; + + if(ulDlCfgIdx == 0) + { + /* Calculate the ReTxIdx corresponding to hqFdbkIdx[0] */ + cellUl->reTxIdx[0] = rgSchUtlCfg0ReTxIdx(cell,timeInfo, + cellUl->hqFdbkIdx[0]); + if(Mval == 2) + { + /* At Idx 1 store the UL SF adjacent(left) to the UL SF + given at idx 0 */ + cellUl->hqFdbkIdx[1] = (cellUl->hqFdbkIdx[0]-1 + + cellUl->numUlSubfrms) % cellUl->numUlSubfrms; + /* Calculate the ReTxIdx corresponding to hqFdbkIdx[1] */ + cellUl->reTxIdx[1] = rgSchUtlCfg0ReTxIdx(cell,timeInfo, + cellUl->hqFdbkIdx[1]); + } + } + } + + idx = (cell->crntTime.subframe + TFU_RECPREQ_DLDELTA) % RGSCH_NUM_SUB_FRAMES; + if (rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] == RG_SCH_TDD_UL_SUBFRAME) + { + RGSCHCMNADDTOCRNTTIME(cell->crntTime, timeInfo, TFU_RECPREQ_DLDELTA) + cellUl->rcpReqIdx = rgSCHCmnGetUlSfIdx(&timeInfo, cell); + } + idx = (cell->crntTime.subframe+RG_SCH_CMN_DL_DELTA) % RGSCH_NUM_SUB_FRAMES; + + /*[ccpu00134666]-MOD-Modify the check to schedule the RAR in + special subframe */ + if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] != RG_SCH_TDD_UL_SUBFRAME) + { + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo,RG_SCH_CMN_DL_DELTA) + msg3Subfrm = rgSchTddMsg3SubfrmTbl[ulDlCfgIdx][timeInfo.subframe]; + RGSCHCMNADDTOCRNTTIME(timeInfo, timeInfo, msg3Subfrm); + cellUl->msg3SchdIdx = rgSCHCmnGetUlSfIdx(&timeInfo, cell); + cellUl->msg3SchdHqProcIdx = rgSCHCmnGetUlHqProcIdx(&timeInfo, cell); + } +#ifdef LTEMAC_SPS + if(!rgSchTddSpsUlRsrvTbl[ulDlCfgIdx][idx]) + { + cellUl->spsUlRsrvIdx = RGSCH_INVALID_INFO; + } + else + { + /* introduce some reuse with above code? */ + U8 offst; + RGSCHCMNADDTOCRNTTIME(cell->crntTime,timeInfo,RG_SCH_CMN_DL_DELTA) + //offst = rgSchTddMsg3SubfrmTbl[ulDlCfgIdx][timeInfo.subframe]; + offst = rgSchTddSpsUlRsrvTbl[ulDlCfgIdx][timeInfo.subframe]; + RGSCHCMNADDTOCRNTTIME(timeInfo, timeInfo, offst); + cellUl->spsUlRsrvIdx = rgSCHCmnGetUlSfIdx(&timeInfo, cell); + /* The harq proc continues to be accessed and used the same delta before + * actual data occurance, and hence use the same idx */ + cellUl->spsUlRsrvHqProcIdx = cellUl->schdHqProcIdx; + } +#endif + + /* RACHO: update cmn sched specific RACH variables, + * mainly the prachMaskIndex */ + rgSCHCmnUpdRachParam(cell); + + RETVOID; +} + +/** + * @brief To get 'p' value from nCCE. + * + * @details + * + * Function: rgSCHCmnGetPValFrmCCE + * Purpose: Gets 'p' value for HARQ ACK/NACK reception from CCE. + * + * @param[in] RgSchCellCb *cell + * @param[in] U8 cce + * @return U8 + * + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnGetPValFrmCCE +( +RgSchCellCb *cell, +U8 cce +) +#else +PUBLIC U8 rgSCHCmnGetPValFrmCCE(cell, cce) +RgSchCellCb *cell; +U8 cce; +#endif +{ + U8 i; + TRC2(rgSCHCmnGetPValFrmCCE); + + for(i=1; i < RGSCH_TDD_MAX_P_PLUS_ONE_VAL; i++) + { + if(cce < cell->rgSchTddNpValTbl[i]) + { + RETVALUE(i-1); + } + } + RETVALUE(0); +} +#endif + +/*********************************************************** + * + * Func : rgSCHCmnUlAdapRetx + * + * Desc : Adaptive retransmission for an allocation. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlAdapRetx +( +RgSchUlAlloc *alloc, +RgSchUlHqProcCb *proc +) +#else +PRIVATE Void rgSCHCmnUlAdapRetx(alloc, proc) +RgSchUlAlloc *alloc; +RgSchUlHqProcCb *proc; +#endif +{ + TRC2(rgSCHCmnUlAdapRetx); + + rgSCHUhmRetx(proc, alloc); +#ifndef RG_5GTF + if (proc->rvIdx != 0) + { + alloc->grnt.iMcsCrnt = rgSchCmnUlRvIdxToIMcsTbl[proc->rvIdx]; + } + else +#endif + { + alloc->grnt.iMcsCrnt = alloc->grnt.iMcs; + } + RETVOID; +} + +/** + * @brief Scheduler invocation per TTI. + * + * @details + * + * Function: rgSCHCmnHdlUlInactUes + * Purpose: + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnHdlUlInactUes +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnHdlUlInactUes(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + CmLListCp ulInactvLst; + TRC2(rgSCHCmnHdlUlInactUes); + /* Get a List of Inactv UEs for UL*/ + cmLListInit(&ulInactvLst); + + /* Trigger Spfc Schedulers with Inactive UEs */ + rgSCHMeasGapANRepGetUlInactvUe (cell, &ulInactvLst); + /* take care of this in UL retransmission */ + cellSch->apisUl->rgSCHUlInactvtUes(cell, &ulInactvLst); + + RETVOID; +} + +/** + * @brief Scheduler invocation per TTI. + * + * @details + * + * Function: rgSCHCmnHdlDlInactUes + * Purpose: + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnHdlDlInactUes +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnHdlDlInactUes(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + CmLListCp dlInactvLst; + TRC2(rgSCHCmnHdlDlInactUes); + /* Get a List of Inactv UEs for DL */ + cmLListInit(&dlInactvLst); + + /* Trigger Spfc Schedulers with Inactive UEs */ + rgSCHMeasGapANRepGetDlInactvUe (cell, &dlInactvLst); + + cellSch->apisDl->rgSCHDlInactvtUes(cell, &dlInactvLst); + RETVOID; +} + +/* RACHO: Rach handover functions start here */ +/*********************************************************** + * + * Func : rgSCHCmnUeIdleExdThrsld + * + * Desc : RETURN ROK if UE has been idle more + * than threshold. + * + * Ret : + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUeIdleExdThrsld +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE S16 rgSCHCmnUeIdleExdThrsld(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + /* Time difference in subframes */ + U32 sfDiff = RGSCH_CALC_SF_DIFF(cell->crntTime, ue->ul.ulTransTime); + + TRC2(rgSCHCmnUeIdleExdThrsld); + + if (sfDiff > (U32)RG_SCH_CMN_UE_IDLE_THRSLD(ue)) + { + RETVALUE(ROK); + } + else + { + RETVALUE(RFAILED); + } +} + + +/** + * @brief Scheduler processing for Ded Preambles on cell configuration. + * + * @details + * + * Function : rgSCHCmnCfgRachDedPrm + * + * This function does requisite initialisation + * for RACH Ded Preambles. + * + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnCfgRachDedPrm +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnCfgRachDedPrm(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + U32 gap = RG_SCH_CMN_MIN_PRACH_OPPR_GAP; + U32 sfDiff; + U8 cnt; + TRC2(rgSCHCmnCfgRachDedPrm); + + if (cell->macPreambleSet.pres == NOTPRSNT) + { + RETVOID; + } + cellSch->rachCfg.numDedPrm = cell->macPreambleSet.size; + cellSch->rachCfg.dedPrmStart = cell->macPreambleSet.start; + /* Initialize handover List */ + cmLListInit(&cellSch->rachCfg.hoUeLst); + /* Initialize pdcch Order List */ + cmLListInit(&cellSch->rachCfg.pdcchOdrLst); + + /* Intialize the rapId to UE mapping structure */ + for (cnt = 0; cntrachCfg.numDedPrm; cnt++) + { + cellSch->rachCfg.rapIdMap[cnt].rapId = cellSch->rachCfg.dedPrmStart + \ + cnt; + cmLListInit(&cellSch->rachCfg.rapIdMap[cnt].assgndUes); + } + /* Perform Prach Mask Idx, remDedPrm, applFrm initializations */ + /* Set remDedPrm as numDedPrm */ + cellSch->rachCfg.remDedPrm = cellSch->rachCfg.numDedPrm; + /* Initialize applFrm */ + cellSch->rachCfg.prachMskIndx = 0; + if (cell->rachCfg.raOccasion.sfnEnum == RGR_SFN_EVEN) + { + cellSch->rachCfg.applFrm.sfn = (cell->crntTime.sfn + \ + (cell->crntTime.sfn % 2)) % RGSCH_MAX_SFN; + } +#ifdef LTE_TDD + else if (cell->rachCfg.raOccasion.sfnEnum == RGR_SFN_ODD) + { + if((cell->crntTime.sfn%2) == 0) + { + cellSch->rachCfg.applFrm.sfn = (cell->crntTime.sfn + 1)\ + % RGSCH_MAX_SFN; + } + } +#endif + else /* ANY sfn */ + { + cellSch->rachCfg.applFrm.sfn = cell->crntTime.sfn; + } + /* Initialize cellSch->rachCfg.applFrm as >= crntTime. + * This is because of RGSCH_CALC_SF_DIFF logic */ + if (cellSch->rachCfg.applFrm.sfn == cell->crntTime.sfn) + { + while (cellSch->rachCfg.prachMskIndx < cell->rachCfg.raOccasion.size) + { + if (cell->crntTime.subframe <\ + cell->rachCfg.raOccasion.subFrameNum[cellSch->rachCfg.prachMskIndx]) + { + break; + } + cellSch->rachCfg.prachMskIndx++; + } + if (cellSch->rachCfg.prachMskIndx == cell->rachCfg.raOccasion.size) + { + if (cell->rachCfg.raOccasion.sfnEnum == RGR_SFN_ANY) + { + cellSch->rachCfg.applFrm.sfn = (cellSch->rachCfg.applFrm.sfn+1) %\ + RGSCH_MAX_SFN; + } + else + { + cellSch->rachCfg.applFrm.sfn = (cellSch->rachCfg.applFrm.sfn+2) %\ + RGSCH_MAX_SFN; + } + cellSch->rachCfg.prachMskIndx = 0; + } + cellSch->rachCfg.applFrm.subframe = \ + cell->rachCfg.raOccasion.subFrameNum[cellSch->rachCfg.prachMskIndx]; + } + else + { + cellSch->rachCfg.applFrm.subframe = \ + cell->rachCfg.raOccasion.subFrameNum[cellSch->rachCfg.prachMskIndx]; + } + + /* Note first param to this macro should always be the latest in time */ + sfDiff = RGSCH_CALC_SF_DIFF(cellSch->rachCfg.applFrm, cell->crntTime); + while (sfDiff <= gap) + { + rgSCHCmnUpdNxtPrchMskIdx(cell); + sfDiff = RGSCH_CALC_SF_DIFF(cellSch->rachCfg.applFrm, cell->crntTime); + } + + RETVOID; +} + +/** + * @brief Updates the PRACH MASK INDEX. + * + * @details + * + * Function: rgSCHCmnUpdNxtPrchMskIdx + * Purpose: Ensures the "applFrm" field of Cmn Sched RACH + * CFG is always >= "n"+"DELTA", where "n" is the crntTime + * of the cell. If not, applFrm is updated to the next avl + * PRACH oppurtunity as per the PRACH Cfg Index configuration. + * + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdNxtPrchMskIdx +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnUpdNxtPrchMskIdx(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + TRC2(rgSCHCmnUpdNxtPrchMskIdx); + + /* Determine the next prach mask Index */ + if (cellSch->rachCfg.prachMskIndx == cell->rachCfg.raOccasion.size - 1) + { + /* PRACH within applFrm.sfn are done, go to next AVL sfn */ + cellSch->rachCfg.prachMskIndx = 0; + if (cell->rachCfg.raOccasion.sfnEnum == RGR_SFN_ANY) + { + cellSch->rachCfg.applFrm.sfn = (cellSch->rachCfg.applFrm.sfn+1) % \ + RGSCH_MAX_SFN; + } + else/* RGR_SFN_EVEN or RGR_SFN_ODD */ + { + cellSch->rachCfg.applFrm.sfn = (cellSch->rachCfg.applFrm.sfn+2) % \ + RGSCH_MAX_SFN; + } + cellSch->rachCfg.applFrm.subframe = cell->rachCfg.raOccasion.\ + subFrameNum[0]; + } + else /* applFrm.sfn is still valid */ + { + cellSch->rachCfg.prachMskIndx += 1; + if ( cellSch->rachCfg.prachMskIndx < RGR_MAX_SUBFRAME_NUM ) + { + cellSch->rachCfg.applFrm.subframe = \ + cell->rachCfg.raOccasion.subFrameNum[cellSch->rachCfg.prachMskIndx]; + } + } + RETVOID; +} + +/** + * @brief Updates the Ded preamble RACH parameters + * every TTI. + * + * @details + * + * Function: rgSCHCmnUpdRachParam + * Purpose: Ensures the "applFrm" field of Cmn Sched RACH + * CFG is always >= "n"+"6"+"DELTA", where "n" is the crntTime + * of the cell. If not, applFrm is updated to the next avl + * PRACH oppurtunity as per the PRACH Cfg Index configuration, + * accordingly the "remDedPrm" is reset to "numDedPrm" and + * "prachMskIdx" field is updated as per "applFrm". + * + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUpdRachParam +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnUpdRachParam(cell) +RgSchCellCb *cell; +#endif +{ + + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + U32 gap = RG_SCH_CMN_MIN_PRACH_OPPR_GAP; + U32 sfDiff; + TRC2(rgSCHCmnUpdRachParam); + + if (cell->macPreambleSet.pres == NOTPRSNT) + { + RETVOID; + } + sfDiff = RGSCH_CALC_SF_DIFF(cellSch->rachCfg.applFrm, \ + cell->crntTime); + if (sfDiff > gap) + { + /* applFrm is still a valid next Prach Oppurtunity */ + RETVOID; + } + rgSCHCmnUpdNxtPrchMskIdx(cell); + /* Reset remDedPrm as numDedPrm */ + cellSch->rachCfg.remDedPrm = cellSch->rachCfg.numDedPrm; + + RETVOID; +} + +/** + * @brief Dedicated Preamble allocation function. + * + * @details + * + * Function: rgSCHCmnAllocPOParam + * Purpose: Allocate pdcch, rapId and PrachMskIdx. + * Set mapping of UE with the allocated rapId. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchUeCb *ue + * @param[out] RgSchPdcch **pdcch + * @param[out] U8 *rapId + * @param[out] U8 *prachMskIdx + * @return Void + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnAllocPOParam +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchUeCb *ue, +RgSchPdcch **pdcch, +U8 *rapId, +U8 *prachMskIdx +) +#else +PRIVATE S16 rgSCHCmnAllocPOParam(cell, dlSf, ue, pdcch, rapId, prachMskIdx) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchUeCb *ue; +RgSchPdcch **pdcch; +U8 *rapId; +U8 *prachMskIdx; +#endif +{ + + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnAllocPOParam); + + if (cell->macPreambleSet.pres == PRSNT_NODEF) + { + if (cellSch->rachCfg.remDedPrm == 0) + { + RETVALUE(RFAILED); + } + /* DTX Changes: One Variable is passed to check whether it is DTX or Not */ + if ((*pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_1A, FALSE)) == NULLP) + { + RETVALUE(RFAILED); + } + /* The stored prachMskIdx is the index of PRACH Oppurtunities in + * raOccasions.subframes[]. + * Converting the same to the actual PRACHMskIdx to be transmitted. */ + *prachMskIdx = cellSch->rachCfg.prachMskIndx + 1; + /* Distribution starts from dedPrmStart till dedPrmStart + numDedPrm */ + *rapId = cellSch->rachCfg.dedPrmStart + + cellSch->rachCfg.numDedPrm - cellSch->rachCfg.remDedPrm; + cellSch->rachCfg.remDedPrm--; + /* Map UE with the allocated RapId */ + ueDl->rachInfo.asgnOppr = cellSch->rachCfg.applFrm; + RGSCH_ARRAY_BOUND_CHECK_WITH_POS_IDX(cell->instIdx, cellSch->rachCfg.rapIdMap, (*rapId - cellSch->rachCfg.dedPrmStart)); + cmLListAdd2Tail(&cellSch->rachCfg.rapIdMap[*rapId - cellSch->rachCfg.dedPrmStart].assgndUes, + &ueDl->rachInfo.rapIdLnk); + ueDl->rachInfo.rapIdLnk.node = (PTR)ue; + ueDl->rachInfo.poRapId = *rapId; + } + else /* if dedicated preambles not configured */ + { + /* DTX Changes: One Variable is passed to check whether it is DTX or Not */ + if ((*pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_1A, FALSE)) == NULLP) + { + RETVALUE(RFAILED); + } + *prachMskIdx = 0; + *rapId = 0; + } + + RETVALUE(ROK); +} + +/** + * @brief Dowlink Scheduling Handler. + * + * @details + * + * Function: rgSCHCmnGenPdcchOrder + * Purpose: For each UE in PO Q, grab a PDCCH, + * get an available ded RapId and fill PDCCH + * with PO information. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnGenPdcchOrder +( +RgSchCellCb *cell, +RgSchDlSf *dlSf +) +#else +PRIVATE Void rgSCHCmnGenPdcchOrder(cell, dlSf) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + CmLList *node = cellSch->rachCfg.pdcchOdrLst.first; + RgSchUeCb *ue; + U8 rapId; + U8 prachMskIdx; + RgSchPdcch *pdcch = NULLP; + + TRC2(rgSCHCmnGenPdcchOrder); + + while (node) + { + ue = (RgSchUeCb *)node->node; + node = node->next; + /* Skip sending for this subframe is Measuring or inActive in UL due + * to MeasGap or inactie due to DRX + */ + if ((ue->measGapCb.isMeasuring == TRUE) || + (ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE) || + (ue->isDrxEnabled && + ue->dl.dlInactvMask & RG_DRX_INACTIVE) + ) + { + continue; + } + if (rgSCHCmnAllocPOParam(cell, dlSf, ue, &pdcch, &rapId,\ + &prachMskIdx) != ROK) + { + /* No More rapIds left for the valid next avl Oppurtunity. + * Unsatisfied UEs here would be given a chance, when the + * prach Mask Index changes as per rachUpd every TTI */ + + /* PDDCH can also be ordered with rapId=0, prachMskIdx=0 + * so that UE triggers a RACH procedure with non-dedicated preamble. + * But the implementation here does not do this. Instead, the "break" + * here implies, that PDCCH Odr always given with valid rapId!=0, + * prachMskIdx!=0 if dedicated preambles are configured. + * If not configured, then trigger a PO with rapId=0,prchMskIdx=0*/ + break; + } + /* Fill pdcch with pdcch odr information */ + rgSCHCmnFillPdcchOdr2Sf(cell, ue, pdcch, rapId, prachMskIdx); + /* Remove this UE from the PDCCH ORDER QUEUE */ + rgSCHCmnDlRmvFrmPdcchOdrQ(cell, ue); + /* Reset UE's power state */ + rgSCHPwrUeReset(cell, ue); + } + RETVOID; +} + + +/** + * @brief This function add UE to PdcchOdr Q if not already present. + * + * @details + * + * Function: rgSCHCmnDlAdd2PdcchOdrQ + * Purpose: + * + * Invoked by: CMN Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ue + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAdd2PdcchOdrQ +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnDlAdd2PdcchOdrQ(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnDlAdd2PdcchOdrQ); + + if (ueDl->rachInfo.poLnk.node == NULLP) + { + cmLListAdd2Tail(&cellSch->rachCfg.pdcchOdrLst, &ueDl->rachInfo.poLnk); + ueDl->rachInfo.poLnk.node = (PTR)ue; + } + RETVOID; +} + + +/** + * @brief This function rmvs UE to PdcchOdr Q if not already present. + * + * @details + * + * Function: rgSCHCmnDlRmvFrmPdcchOdrQ + * Purpose: + * + * Invoked by: CMN Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchUeCb* ue + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRmvFrmPdcchOdrQ +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnDlRmvFrmPdcchOdrQ(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnDlRmvFrmPdcchOdrQ); + + cmLListDelFrm(&cellSch->rachCfg.pdcchOdrLst, &ueDl->rachInfo.poLnk); + ueDl->rachInfo.poLnk.node = NULLP; + RETVOID; +} + +/** + * @brief Fill pdcch with PDCCH order information. + * + * @details + * + * Function: rgSCHCmnFillPdcchOdr2Sf + * Purpose: Fill PDCCH with PDCCH order information, + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchUeCb *ue + * @param[in] RgSchPdcch *pdcch + * @param[in] U8 rapId + * @param[in] U8 prachMskIdx + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFillPdcchOdr2Sf +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchPdcch *pdcch, +U8 rapId, +U8 prachMskIdx +) +#else +PRIVATE Void rgSCHCmnFillPdcchOdr2Sf(ue, pdcch, rapId, prachMskIdx) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchPdcch *pdcch; +U8 rapId; +U8 prachMskIdx; +#endif +{ + RgSchUeACqiCb *acqiCb = RG_SCH_CMN_GET_ACQICB(ue,cell); + + TRC2(rgSCHCmnFillPdcchOdr2Sf); + + pdcch->rnti = ue->ueId; + pdcch->dci.dciFormat = TFU_DCI_FORMAT_1A; + pdcch->dci.u.format1aInfo.isPdcchOrder = TRUE; + pdcch->dci.u.format1aInfo.t.pdcchOrder.preambleIdx = rapId; + pdcch->dci.u.format1aInfo.t.pdcchOrder.prachMaskIdx = prachMskIdx; + + /* Request for APer CQI immediately after PDCCH Order */ + /* CR ccpu00144525 */ +#ifdef TFU_UPGRADE + if(ue->dl.ueDlCqiCfg.aprdCqiCfg.pres) + { + ue->dl.reqForCqi = RG_SCH_APCQI_SERVING_CC; + acqiCb->aCqiTrigWt = 0; + } +#endif + + RETVOID; +} + + +/** + * @brief UE deletion for scheduler. + * + * @details + * + * Function : rgSCHCmnDelRachInfo + * + * This functions deletes all scheduler information + * pertaining to an UE. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDelRachInfo +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnDelRachInfo(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 rapIdIdx; + + TRC2(rgSCHCmnDelRachInfo); + + if (ueDl->rachInfo.poLnk.node) + { + rgSCHCmnDlRmvFrmPdcchOdrQ(cell, ue); + } + if (ueDl->rachInfo.hoLnk.node) + { + cmLListDelFrm(&cellSch->rachCfg.hoUeLst, &ueDl->rachInfo.hoLnk); + ueDl->rachInfo.hoLnk.node = NULLP; + } + if (ueDl->rachInfo.rapIdLnk.node) + { + rapIdIdx = ueDl->rachInfo.poRapId - cellSch->rachCfg.dedPrmStart; + cmLListDelFrm(&cellSch->rachCfg.rapIdMap[rapIdIdx].assgndUes, + &ueDl->rachInfo.rapIdLnk); + ueDl->rachInfo.rapIdLnk.node = NULLP; + } + RETVOID; +} + +/** + * @brief This function retrieves the ue which has sent this raReq + * and it allocates grant for UEs undergoing (for which RAR + * is being generated) HandOver/PdcchOrder. + * + * + * @details + * + * Function: rgSCHCmnHdlHoPo + * Purpose: This function retrieves the ue which has sent this raReq + * and it allocates grant for UEs undergoing (for which RAR + * is being generated) HandOver/PdcchOrder. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] CmLListCp *raRspLst + * @param[in] RgSchRaReqInfo *raReq + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnHdlHoPo +( +RgSchCellCb *cell, +CmLListCp *raRspLst, +RgSchRaReqInfo *raReq +) +#else +PRIVATE Void rgSCHCmnHdlHoPo(cell, raRspLst, raReq) +RgSchCellCb *cell; +CmLListCp *raRspLst; +RgSchRaReqInfo *raReq; +#endif +{ + RgSchUeCb *ue = raReq->ue; + TRC2(rgSCHCmnHdlHoPo); + + if ( ue->isDrxEnabled ) + { + rgSCHDrxDedRa(cell,ue); + } + rgSCHCmnAllocPoHoGrnt(cell, raRspLst, ue, raReq); + RETVOID; +} + +/** + * @brief This function retrieves the UE which has sent this raReq + * for handover case. + * + * + * @details + * + * Function: rgSCHCmnGetHoUe + * Purpose: This function retrieves the UE which has sent this raReq + * for handover case. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchRaReqInfo *raReq + * @return RgSchUeCb* + * + **/ +#ifdef ANSI +PUBLIC RgSchUeCb* rgSCHCmnGetHoUe +( +RgSchCellCb *cell, +U16 rapId +) +#else +PUBLIC RgSchUeCb* rgSCHCmnGetHoUe(cell, rapId) +RgSchCellCb *cell; +U16 rapId +#endif +{ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + CmLList *node; + CmLListCp *ueLst; + RgSchUeCb *ue; + RgSchCmnDlUe *ueDl; + TRC2(rgSCHCmnGetHoUe); + + ueLst = &cellSch->rachCfg.hoUeLst; + node = ueLst->first; + while (node) + { + ue = (RgSchUeCb *)node->node; + node = node->next; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + if (ueDl->rachInfo.hoRapId == rapId) + { + RETVALUE(ue); + } + } + RETVALUE(NULLP); +} + +#ifdef ANSI +PRIVATE Void rgSCHCmnDelDedPreamble +( +RgSchCellCb *cell, +U8 preambleId +) +#else +PRIVATE rgSCHCmnDelDedPreamble(cell, preambleId) +RgSchCellCb *cell; +U8 preambleId; +#endif +{ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + CmLList *node; + CmLListCp *ueLst; + RgSchUeCb *ue; + RgSchCmnDlUe *ueDl; + TRC2(rgSCHCmnDelDedPreamble); + + ueLst = &cellSch->rachCfg.hoUeLst; + node = ueLst->first; + while (node) + { + ue = (RgSchUeCb *)node->node; + node = node->next; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + if (ueDl->rachInfo.hoRapId == preambleId) + { + cmLListDelFrm(ueLst, &ueDl->rachInfo.hoLnk); + ueDl->rachInfo.hoLnk.node = (PTR)NULLP; + } + } +} + +/** + * @brief This function retrieves the UE which has sent this raReq + * for PDCCh Order case. + * + * + * @details + * + * Function: rgSCHCmnGetPoUe + * Purpose: This function retrieves the UE which has sent this raReq + * for PDCCH Order case. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchRaReqInfo *raReq + * @return RgSchUeCb* + * + **/ +#ifdef ANSI +PUBLIC RgSchUeCb* rgSCHCmnGetPoUe +( +RgSchCellCb *cell, +U16 rapId, +CmLteTimingInfo timingInfo +) +#else +PUBLIC RgSchUeCb* rgSCHCmnGetPoUe(cell, rapId, timingInfo) +RgSchCellCb *cell; +U16 rapId; +CmLteTimingInfo timingInfo; +#endif +{ + RgSchCmnCell *cellSch = (RgSchCmnCell *)(cell->sc.sch); + CmLList *node; + CmLListCp *ueLst; + RgSchUeCb *ue; + RgSchCmnDlUe *ueDl; + U8 rapIdIdx; + TRC2(rgSCHCmnGetPoUe); + + rapIdIdx = rapId -cellSch->rachCfg.dedPrmStart; + ueLst = &cellSch->rachCfg.rapIdMap[rapIdIdx].assgndUes; + node = ueLst->first; + while (node) + { + ue = (RgSchUeCb *)node->node; + node = node->next; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + /* Remove UEs irrespective. + * Old UE associations are removed.*/ + cmLListDelFrm(ueLst, &ueDl->rachInfo.rapIdLnk); + ueDl->rachInfo.rapIdLnk.node = (PTR)NULLP; + if (RGSCH_TIMEINFO_SAME(ueDl->rachInfo.asgnOppr, timingInfo)) + { + RETVALUE(ue); + } + } + + RETVALUE(NULLP); +} + + +/** + * @brief This function returns the valid UL cqi for a given UE. + * + * @details + * + * Function: rgSCHCmnUlGetCqi + * Purpose: This function returns the "valid UL cqi" for a given UE + * based on UE category + * + * Invoked by: Scheduler + * + * @param[in] RgSchUeCb *ue + * @param[in] U8 ueCtgy + * @return U8 + **/ +#ifdef ANSI +PUBLIC U8 rgSCHCmnUlGetCqi +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteUeCategory ueCtgy +) +#else +PUBLIC U8 rgSCHCmnUlGetCqi(cell, ue, ueCtgy) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteUeCategory ueCtgy; +#endif +{ + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + U8 cqi; + + TRC2(rgSCHCmnUlGetCqi); + + cqi = ueUl->maxUlCqi; +#ifdef TFU_UPGRADE + if (!((ueCtgy != CM_LTE_UE_CAT_5) && + (ueUl->validUlCqi > ueUl->maxUlCqi))) + { + cqi = ueUl->validUlCqi; + } +#else + if (!((ueCtgy != CM_LTE_UE_CAT_5) && + (ueUl->crntUlCqi[0] > ueUl->maxUlCqi ))) + { + cqi = ueUl->crntUlCqi[0]; + } +#endif + RETVALUE(cqi); +}/* End of rgSCHCmnUlGetCqi */ + +/*********************************************************** + * + * Func : rgSCHCmnUlRbAllocForPoHoUe + * + * Desc : Do uplink RB allocation for a HO/PO UE. + * + * Ret : + * + * Notes: Note that as of now, for retx, maxRb + * is not considered. Alternatives, such + * as dropping retx if it crosses maxRb + * could be considered. + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUlRbAllocForPoHoUe +( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUeCb *ue, +U8 maxRb +) +#else +PRIVATE S16 rgSCHCmnUlRbAllocForPoHoUe(cell, sf, ue, maxRb) +RgSchCellCb *cell; +RgSchUlSf *sf; +RgSchUeCb *ue; +U8 maxRb; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + U8 sbSize = cellUl->sbSize; + U32 maxBits = ue->ul.maxBytesPerUePerTti*8; + U32 bits; + RgSchUlAlloc *alloc; + U32 nPrb; + U8 iTbs; + U32 eff; + U32 numSb; + U8 iMcs; + U8 iMcsCrnt; + U8 cqi; + U8 modOdr; + RgSchUlHole *hole; + RgSchUlHqProcCb *proc = &ueUl->hqEnt.hqProcCb[cellUl->msg3SchdHqProcIdx]; + CmLteUeCategory ueCtg = (CmLteUeCategory)(RG_SCH_CMN_GET_UE_CTGY(ue)); + + TRC2(rgSCHCmnUlRbAllocForPoHoUe); + if ((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP) + { + RETVALUE(RFAILED); + } + /*MS_WORKAROUND for HO ccpu00121116*/ + cqi = rgSCHCmnUlGetCqi(cell, ue, ueCtg); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgSchCmnUlCqiToTbsTbl[(U8)cell->isCpUlExtend], cqi); + iTbs = rgSchCmnUlCqiToTbsTbl[(U8)cell->isCpUlExtend][cqi]; + iMcs = rgSCHCmnUlGetIMcsFrmITbs(iTbs,ueCtg); + while(iMcs > RG_SCH_CMN_MAX_MSG3_IMCS) + { + cqi--; + iTbs = rgSchCmnUlCqiToTbsTbl[(U8)cell->isCpUlExtend][cqi]; + iMcs = rgSCHCmnUlGetIMcsFrmITbs(iTbs, ueCtg); + } + /* Filling the modorder in the grant structure*/ + RG_SCH_UL_MCS_TO_MODODR(iMcs,modOdr); + if (!cell->isCpUlExtend) + { + eff = rgSchCmnNorUlEff[0][iTbs]; + } + else + { + eff = rgSchCmnExtUlEff[0][iTbs]; + } + + bits = ueUl->alloc.reqBytes * 8; + +#if (ERRCLASS & ERRCLS_DEBUG) + if (!bits) + { + RETVALUE(RFAILED); + } +#endif + + if (bits < rgSCHCmnUlMinTbBitsForITbs(cellUl, iTbs)) + { + numSb = 1; + nPrb = numSb * sbSize; + } + else + { + if (bits > maxBits) + { + bits = maxBits; + nPrb = bits * 1024 / eff / RG_SCH_CMN_UL_NUM_RE_PER_RB(cellUl); + if (nPrb > maxRb) + { + nPrb = maxRb; + } + numSb = nPrb / sbSize; + } + else + { + /*ccpu00128775:MOD-Change to get upper threshold nPrb*/ + nPrb = RGSCH_CEIL((RGSCH_CEIL(bits * 1024, eff)), + RG_SCH_CMN_UL_NUM_RE_PER_RB(cellUl)); + if (nPrb > maxRb) + { + nPrb = maxRb; + } + numSb = RGSCH_DIV_ROUND(nPrb, sbSize); + } + } + iMcsCrnt = iMcs; + + alloc = rgSCHCmnUlSbAlloc(sf, (U8)RGSCH_MIN(numSb, cellUl->maxSbPerUe),\ + hole); + if (alloc == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnUlRbAllocForPoHoUe(): Could not get UlAlloc"); + RETVALUE(RFAILED); + } + rgSCHCmnUlAllocFillRbInfo(cell, sf, alloc); + + /* Filling the modorder in the grant structure start*/ + alloc->grnt.modOdr = (TfuModScheme) modOdr; + alloc->grnt.iMcs = iMcs; + alloc->grnt.iMcsCrnt = iMcsCrnt; + alloc->grnt.hop = 0; + /* Fix for ccpu00123915*/ + alloc->forMsg3 = TRUE; + alloc->hqProc = proc; + alloc->hqProc->ulSfIdx = cellUl->msg3SchdIdx; + alloc->ue = ue; + alloc->rnti = ue->ueId; + /* updating initNumRbs in case of HO */ +#ifdef TFU_UPGRADE + ue->initNumRbs = alloc->grnt.numRb; +#endif + ueUl->alloc.alloc = alloc; + iTbs = rgSCHCmnUlGetITbsFrmIMcs(iMcs); + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgTbSzTbl[0], iTbs); + alloc->grnt.datSz = rgTbSzTbl[0][iTbs][alloc->grnt.numRb-1] / 8; + /* MS_WORKAROUND for HO ccpu00121124*/ + /*[Adi temp change] Need to fil modOdr */ + RG_SCH_UL_MCS_TO_MODODR(alloc->grnt.iMcsCrnt,alloc->grnt.modOdr); + rgSCHUhmNewTx(proc, ueUl->hqEnt.maxHqRetx, alloc); + /* No grant attr recorded now */ + RETVALUE(ROK); +} + +/** + * @brief This function allocates grant for UEs undergoing (for which RAR + * is being generated) HandOver/PdcchOrder. + * + * + * @details + * + * Function: rgSCHCmnAllocPoHoGrnt + * Purpose: This function allocates grant for UEs undergoing (for which RAR + * is being generated) HandOver/PdcchOrder. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[out] CmLListCp *raRspLst, + * @param[in] RgSchUeCb *ue + * @param[in] RgSchRaReqInfo *raReq + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnAllocPoHoGrnt +( +RgSchCellCb *cell, +CmLListCp *raRspLst, +RgSchUeCb *ue, +RgSchRaReqInfo *raReq +) +#else +PRIVATE Void rgSCHCmnAllocPoHoGrnt(cell, raRspLst, ue, raReq) +RgSchCellCb *cell; +CmLListCp *raRspLst; +RgSchUeCb *ue; +RgSchRaReqInfo *raReq; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue,cell); + RgSchUlGrnt *grnt; + RgSchUlSf *sf = &cellUl->ulSfArr[cellUl->msg3SchdIdx]; + + TRC2(rgSCHCmnAllocPoHoGrnt); + + /* Clearing previous allocs if any*/ + rgSCHCmnUlUeDelAllocs(cell, ue); + /* Fix : syed allocs are limited */ + if (*sf->allocCountRef >= cellUl->maxAllocPerUlSf) + { + RETVOID; + } + ueUl->alloc.reqBytes = RG_SCH_MIN_GRNT_HOPO; + if (rgSCHCmnUlRbAllocForPoHoUe(cell, sf, ue, RGSCH_MAX_UL_RB) != ROK) + { + RETVOID; + } + + /* Fill grant information */ + grnt = &ueUl->alloc.alloc->grnt; + + /* KWork fix */ + if (grnt == NULLP) + { + RLOG_ARG1(L_ERROR,DBG_INSTID,cell->instIdx, "Failed to get" + "the grant for HO/PDCCH Order. CRNTI:%d",ue->ueId); + RETVOID; + } + ue->ul.rarGrnt.rapId = raReq->raReq.rapId; + ue->ul.rarGrnt.hop = grnt->hop; + ue->ul.rarGrnt.rbStart = grnt->rbStart; + ue->ul.rarGrnt.numRb = grnt->numRb; + ue->ul.rarGrnt.tpc = grnt->tpc; + ue->ul.rarGrnt.iMcsCrnt = grnt->iMcsCrnt; + ue->ul.rarGrnt.ta.pres = TRUE; + ue->ul.rarGrnt.ta.val = raReq->raReq.ta; + ue->ul.rarGrnt.datSz = grnt->datSz; + if((sf->numACqiCount < RG_SCH_MAX_ACQI_PER_ULSF) && (RG_SCH_APCQI_NO != ue->dl.reqForCqi)) + { +#ifdef LTE_ADV + U8 idx = 0; + /* Send two bits cqireq field if more than one cells are configured else one*/ + for (idx = 1;idx < CM_LTE_MAX_CELLS;idx++) + { + if (ue->cellInfo[idx] != NULLP) + { + ue->ul.rarGrnt.cqiReqBit = ue->dl.reqForCqi; + break; + } + } + if (idx == CM_LTE_MAX_CELLS) +#endif + { + ue->ul.rarGrnt.cqiReqBit = ue->dl.reqForCqi; + } + ue->dl.reqForCqi = RG_SCH_APCQI_NO; + sf->numACqiCount++; + } + else + { + ue->ul.rarGrnt.cqiReqBit = 0; + } + /* Attach Ho/Po allocation to RAR Rsp cont free Lst */ + cmLListAdd2Tail(raRspLst, &ue->ul.rarGrnt.raRspLnk); + ue->ul.rarGrnt.raRspLnk.node = (PTR)ue; + + RETVOID; +} + +/** + * @brief This is a utility function to set the fields in + * an UL harq proc which is identified for non-adaptive retx + * + * @details + * + * Function: rgSCHCmnUlNonadapRetx + * Purpose: Sets the fields in UL Harq proc for non-adaptive retx + * + * @param[in] RgSchCmnUlCell *cellUl + * @param[out] RgSchUlAlloc *alloc + * @param[in] U8 idx + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlNonadapRetx +( +RgSchCmnUlCell *cellUl, +RgSchUlAlloc *alloc, +U8 idx +) +#else +PRIVATE Void rgSCHCmnUlNonadapRetx(cellUl, alloc, idx) +RgSchCmnUlCell *cellUl; +RgSchUlAlloc *alloc; +U8 idx; +#endif +{ + TRC2(rgSCHCmnUlNonadapRetx); + rgSCHUhmRetx(alloc->hqProc, alloc); + + /* Update alloc to retx */ + alloc->hqProc->isRetx = TRUE; + alloc->hqProc->ulSfIdx = cellUl->reTxIdx[idx]; + + if (alloc->hqProc->rvIdx != 0) + { + alloc->grnt.iMcsCrnt = rgSchCmnUlRvIdxToIMcsTbl[alloc->hqProc->rvIdx]; + } + else + { + alloc->grnt.iMcsCrnt = alloc->grnt.iMcs; + } + alloc->grnt.isRtx = TRUE; + alloc->pdcch = NULLP; + RETVOID; +} + +/** + * @brief Check if 2 allocs overlap + * + * @details + * + * Function : rgSCHCmnUlAllocsOvrLap + * + * - Return TRUE if alloc1 and alloc2 overlap. + * + * @param[in] RgSchUlAlloc *alloc1 + * @param[in] RgSchUlAlloc *alloc2 + * @return Bool + **/ +#ifdef ANSI +PRIVATE Bool rgSCHCmnUlAllocsOvrLap +( +RgSchUlAlloc *alloc1, +RgSchUlAlloc *alloc2 +) +#else +PRIVATE Bool rgSCHCmnUlAllocsOvrLap(alloc1, alloc2) +RgSchUlAlloc *alloc1; +RgSchUlAlloc *alloc2; +#endif +{ + + TRC2(rgSCHCmnUlAllocsOvrLap); + + if (((alloc1->sbStart >= alloc2->sbStart) && + (alloc1->sbStart <= alloc2->sbStart + alloc2->numSb-1)) || + ((alloc2->sbStart >= alloc1->sbStart) && + (alloc2->sbStart <= alloc1->sbStart + alloc1->numSb-1))) + { + RETVALUE(TRUE); + } + RETVALUE(FALSE); +} + +/** + * @brief Copy allocation Info from src to dst. + * + * @details + * + * Function : rgSCHCmnUlCpyAllocInfo + * + * - Copy allocation Info from src to dst. + * + * @param[in] RgSchUlAlloc *srcAlloc + * @param[in] RgSchUlAlloc *dstAlloc + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlCpyAllocInfo +( +RgSchCellCb *cell, +RgSchUlAlloc *srcAlloc, +RgSchUlAlloc *dstAlloc +) +#else +PRIVATE Void rgSCHCmnUlCpyAllocInfo(cell, srcAlloc, dstAlloc) +RgSchCellCb *cell; +RgSchUlAlloc *srcAlloc; +RgSchUlAlloc *dstAlloc; +#endif +{ + RgSchCmnUlUe *ueUl; + TRC2(rgSCHCmnUlCpyAllocInfo); + + dstAlloc->grnt = srcAlloc->grnt; + dstAlloc->hqProc = srcAlloc->hqProc; + /* Fix : syed During UE context release, hqProc->alloc + * was pointing to srcAlloc instead of dstAlloc and + * freeing from incorrect sf->allocDb was + * corrupting the list. */ + /* In case of SPS Occasion Allocation is done in advance and + at a later time Hq Proc is linked. Hence HqProc + pointer in alloc shall be NULL */ +#ifdef LTEMAC_SPS + if (dstAlloc->hqProc) +#endif + { + dstAlloc->hqProc->alloc = dstAlloc; + } + dstAlloc->ue = srcAlloc->ue; + dstAlloc->rnti = srcAlloc->rnti; + dstAlloc->forMsg3 = srcAlloc->forMsg3; + dstAlloc->raCb = srcAlloc->raCb; + dstAlloc->pdcch = srcAlloc->pdcch; + /* Fix : syed HandIn Ue has forMsg3 and ue Set, but no RaCb */ + if (dstAlloc->ue) + { + ueUl = RG_SCH_CMN_GET_UL_UE(dstAlloc->ue,cell); + ueUl->alloc.alloc = dstAlloc; +#ifdef LTEMAC_SPS + if (dstAlloc->ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + if((dstAlloc->ue->ul.ulSpsInfo.ulSpsSchdInfo.crntAlloc != NULLP) + && (dstAlloc->ue->ul.ulSpsInfo.ulSpsSchdInfo.crntAlloc == srcAlloc)) + { + dstAlloc->ue->ul.ulSpsInfo.ulSpsSchdInfo.crntAlloc = dstAlloc; + } + } +#endif + } + + RETVOID; +} + + +/** + * @brief Update TX and RETX subframe's allocation + * markings. + * + * @details + * + * Function : rgSCHCmnUlInsAllocFrmNewSf2OldSf + * + * - Release all preassigned allocations of newSf and merge + * them to oldSf. + * - If alloc of newSf collide with one or more allocs of oldSf + * - mark all such allocs of oldSf for Adaptive Retx. + * - Swap the alloc and hole DB references of oldSf and newSf. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *newSf + * @param[in] RgSchUlSf *oldSf + * @param[in] RgSchUlAlloc *srcAlloc + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlInsAllocFrmNewSf2OldSf +( +RgSchCellCb *cell, +RgSchUlSf *newSf, +RgSchUlSf *oldSf, +RgSchUlAlloc *srcAlloc +) +#else +PRIVATE Void rgSCHCmnUlInsAllocFrmNewSf2OldSf(cell, newSf, oldSf, srcAlloc) +RgSchCellCb *cell; +RgSchUlSf *newSf; +RgSchUlSf *oldSf; +RgSchUlAlloc *srcAlloc; +#endif +{ + RgSchUlAlloc *alloc, *dstAlloc, *nxtAlloc; + + /* MS_WORKAROUND ccpu00120827 */ + RgSchCmnCell *schCmnCell = (RgSchCmnCell *)(cell->sc.sch); + U8 remAllocs; + TRC2(rgSCHCmnUlInsAllocFrmNewSf2OldSf); + + if ((alloc = rgSCHUtlUlAllocFirst(oldSf)) != NULLP) + { + do + { + nxtAlloc = rgSCHUtlUlAllocNxt(oldSf, alloc); + /* If there is an overlap between alloc and srcAlloc + * then alloc is marked for Adaptive retx and it is released + * from txSf */ + if (rgSCHCmnUlAllocsOvrLap(alloc, srcAlloc) == TRUE) + { + rgSCHCmnUlUpdAllocRetx(cell, alloc); + rgSCHUtlUlAllocRls(oldSf, alloc); + } + /* No further allocs spanning the srcAlloc subbands */ + if (srcAlloc->sbStart + srcAlloc->numSb - 1 <= alloc->sbStart) + { + break; + } + } while ((alloc = nxtAlloc) != NULLP); + } + + /* After freeing all the colliding allocs, request for an allocation + * specifying the start and numSb with in txSf. This function should + * always return positively with a nonNULL dstAlloc */ + /* MS_WORKAROUND ccpu00120827 */ + remAllocs = schCmnCell->ul.maxAllocPerUlSf - *oldSf->allocCountRef; + if (!remAllocs) + { + /* Fix : If oldSf already has max Allocs then release the + * old RETX alloc to make space for new alloc of newSf. + * newSf allocs(i.e new Msg3s) are given higher priority + * over retx allocs. */ + if ((alloc = rgSCHUtlUlAllocFirst(oldSf)) != NULLP) + { + do + { + nxtAlloc = rgSCHUtlUlAllocNxt(oldSf, alloc); + if (!alloc->mrgdNewTxAlloc) + { + /* If alloc is for RETX */ + /* TODO: Incase of this ad also in case of choosing + * and alloc for ADAP RETX, we need to send ACK for + * the corresponding alloc in PHICH */ +#ifndef EMTC_ENABLE + rgSCHCmnUlFreeAllocation(cell, oldSf, alloc); +#else + rgSCHCmnUlFreeAllocation(cell, oldSf, alloc,FALSE); +#endif + break; + } + }while((alloc = nxtAlloc) != NULLP); + } + } + dstAlloc = rgSCHUtlUlGetSpfcAlloc(oldSf, srcAlloc->sbStart, srcAlloc->numSb); +#ifdef ERRCLS_KW + /* This should never happen */ + if (dstAlloc == NULLP) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"CRNTI:%d " + "rgSCHUtlUlGetSpfcAlloc failed in rgSCHCmnUlInsAllocFrmNewSf2OldSf", + srcAlloc->rnti); + RETVOID; + } +#endif + /* Copy the srcAlloc's state information in to dstAlloc */ + rgSCHCmnUlCpyAllocInfo(cell, srcAlloc, dstAlloc); + /* Set new Tx merged Alloc Flag to TRUE, indicating that this + * alloc shall not be processed for non-adaptive retransmission */ + dstAlloc->mrgdNewTxAlloc = TRUE; + RETVOID; +} + +/** + * @brief Merge all allocations of newSf to oldSf. + * + * @details + * + * Function : rgSCHCmnUlMergeSfAllocs + * + * - Merge all allocations of newSf to oldSf. + * - If newSf's alloc collides with oldSf's alloc + * then oldSf's alloc is marked for adaptive Retx + * and is released from oldSf to create space for + * newSf's alloc. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *oldSf + * @param[in] RgSchUlSf *newSf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlMergeSfAllocs +( +RgSchCellCb *cell, +RgSchUlSf *oldSf, +RgSchUlSf *newSf +) +#else +PRIVATE Void rgSCHCmnUlMergeSfAllocs(cell, oldSf, newSf) +RgSchCellCb *cell; +RgSchUlSf *oldSf; +RgSchUlSf *newSf; +#endif +{ + RgSchUlAlloc *alloc, *nxtAlloc; + TRC2(rgSCHCmnUlMergeSfAllocs); + UNUSED(cell); + + /* Merge each alloc of newSf in to oldSf + * and release it from newSf */ + if ((alloc = rgSCHUtlUlAllocFirst(newSf)) != NULLP) + { + do + { + nxtAlloc = rgSCHUtlUlAllocNxt(newSf, alloc); + rgSCHCmnUlInsAllocFrmNewSf2OldSf(cell, newSf, oldSf, alloc); + rgSCHUtlUlAllocRls(newSf, alloc); + } while((alloc = nxtAlloc) != NULLP); + } + RETVOID; +} + +/** + * @brief Swap Hole/Alloc DB context of newSf and oldSf. + * + * @details + * + * Function : rgSCHCmnUlSwapSfAllocs + * + * - Swap Hole/Alloc DB context of newSf and oldSf. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *oldSf + * @param[in] RgSchUlSf *newSf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlSwapSfAllocs +( +RgSchCellCb *cell, +RgSchUlSf *oldSf, +RgSchUlSf *newSf +) +#else +PRIVATE Void rgSCHCmnUlSwapSfAllocs(cell, oldSf, newSf) +RgSchCellCb *cell; +RgSchUlSf *oldSf; +RgSchUlSf *newSf; +#endif +{ + RgSchUlAllocDb *tempAllocDb = newSf->allocDb; + RgSchUlHoleDb *tempHoleDb = newSf->holeDb; + U8 tempAvailSbs = newSf->availSubbands; + + TRC2(rgSCHCmnUlSwapSfAllocs); + UNUSED(cell); + + newSf->allocDb = oldSf->allocDb; + newSf->holeDb = oldSf->holeDb; + newSf->availSubbands = oldSf->availSubbands; + + oldSf->allocDb = tempAllocDb; + oldSf->holeDb = tempHoleDb; + oldSf->availSubbands = tempAvailSbs; + + /* Fix ccpu00120610*/ + newSf->allocCountRef = &newSf->allocDb->count; + oldSf->allocCountRef = &oldSf->allocDb->count; + RETVOID; +} + +/** + * @brief Perform non-adaptive RETX for non-colliding allocs. + * + * @details + * + * Function : rgSCHCmnUlPrcNonAdptRetx + * + * - Perform non-adaptive RETX for non-colliding allocs. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *newSf + * @param[in] U8 idx + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlPrcNonAdptRetx +( +RgSchCellCb *cell, +RgSchUlSf *newSf, +U8 idx +) +#else +PRIVATE Void rgSCHCmnUlPrcNonAdptRetx(cell, newSf, idx) +RgSchCellCb *cell; +RgSchUlSf *newSf; +U8 idx; +#endif +{ + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchUlAlloc *alloc, *nxtAlloc; + TRC2(rgSCHCmnUlPrcNonAdptRetx); + + /* perform non-adaptive retx allocation(adjustment) */ + if ((alloc = rgSCHUtlUlAllocFirst(newSf)) != NULLP) + { + do + { + nxtAlloc = rgSCHUtlUlAllocNxt(newSf, alloc); + /* A merged new TX alloc, reset the state and skip */ + if (alloc->mrgdNewTxAlloc) + { + alloc->mrgdNewTxAlloc = FALSE; + continue; + } + + + rgSCHCmnUlNonadapRetx(cellUl, alloc, idx); + + } while((alloc = nxtAlloc) != NULLP); + } + RETVOID; +} + +/** + * @brief Update TX and RETX subframe's allocation + * markings. + * + * @details + * + * Function : rgSCHCmnUlPrfmSfMerge + * + * - Release all preassigned allocations of newSf and merge + * them to oldSf. + * - If alloc of newSf collide with one or more allocs of oldSf + * - mark all such allocs of oldSf for Adaptive Retx. + * - Swap the alloc and hole DB references of oldSf and newSf. + * - The allocs which did not collide with pre-assigned msg3 + * allocs are marked for non-adaptive RETX. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *oldSf + * @param[in] RgSchUlSf *newSf + * @param[in] U8 idx + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlPrfmSfMerge +( +RgSchCellCb *cell, +RgSchUlSf *oldSf, +RgSchUlSf *newSf, +U8 idx +) +#else +PRIVATE Void rgSCHCmnUlPrfmSfMerge(cell, oldSf, newSf, idx) +RgSchCellCb *cell; +RgSchUlSf *oldSf; +RgSchUlSf *newSf; +U8 idx; +#endif +{ + TRC2(rgSCHCmnUlPrfmSfMerge); + /* Preassigned resources for msg3 in newSf. + * Hence do adaptive retx for all NACKED TXs */ + rgSCHCmnUlMergeSfAllocs(cell, oldSf, newSf); + /* swap alloc and hole DBs of oldSf and newSf. */ + rgSCHCmnUlSwapSfAllocs(cell, oldSf, newSf); + /* Here newSf has the resultant merged allocs context */ + /* Perform non-adaptive RETX for non-colliding allocs */ + rgSCHCmnUlPrcNonAdptRetx(cell, newSf, idx); + + RETVOID; +} + +/** + * @brief Update TX and RETX subframe's allocation + * markings. + * + * @details + * + * Function : rgSCHCmnUlRmvCmpltdAllocs + * + * - Free all Transmission which are ACKED + * OR for which MAX retransmission have + * occurred. + * + * + * @param[in] RgSchCellCb *cell, + * @param[in] RgSchUlSf *sf + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlRmvCmpltdAllocs +( +RgSchCellCb *cell, +RgSchUlSf *sf +) +#else +PRIVATE Void rgSCHCmnUlRmvCmpltdAllocs(cell, sf) +RgSchCellCb *cell; +RgSchUlSf *sf; +#endif +{ + RgSchUlAlloc *alloc, *nxtAlloc; + TRC2(rgSCHCmnUlRmvCmpltdAllocs); + + if ((alloc = rgSCHUtlUlAllocFirst(sf)) == NULLP) + { + RETVOID; + } + do + { + nxtAlloc = rgSCHUtlUlAllocNxt(sf, alloc); +#ifdef UL_ADPT_DBG + printf("rgSCHCmnUlRmvCmpltdAllocs:time(%d %d) alloc->hqProc->remTx %d hqProcId(%d) \n",cell->crntTime.sfn,cell->crntTime.subframe,alloc->hqProc->remTx, alloc->grnt.hqProcId); +#endif + alloc->hqProc->rcvdCrcInd = TRUE; + if ((alloc->hqProc->rcvdCrcInd) || (alloc->hqProc->remTx == 0)) + { + + /* SR_RACH_STATS : MSG 3 MAX RETX FAIL*/ + if ((alloc->forMsg3 == TRUE) && (alloc->hqProc->remTx == 0)) + { + rgNumMsg3FailMaxRetx++; +#ifdef TENB_STATS + cell->tenbStats->sch.msg3Fail++; +#endif + } + +#ifdef MAC_SCH_STATS + if(alloc->ue != NULLP) + { + /* access from ulHarqProc*/ + RgSchUeCb *ueCb = alloc->ue; + RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch; + RgSchCmnUlUe *ulUe = &(cmnUe->ul); + U8 cqi = ulUe->crntUlCqi[0]; + U16 numUlRetx = ueCb->ul.hqEnt.maxHqRetx - alloc->hqProc->remTx; + + hqRetxStats.ulCqiStat[(cqi - 1)].mcs = alloc->grnt.iMcs; + + switch (numUlRetx) + { + case 1: + hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_1++; + break; + case 2: + hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_2++; + break; + case 3: + hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_3++; + break; + case 4: + hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_4++; + break; + } + hqRetxStats.ulCqiStat[(cqi - 1)].totalTx = \ + hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_1 + \ + (hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \ + (hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \ + (hqRetxStats.ulCqiStat[(cqi - 1)].numOfHQ_4 * 4); + } + +#endif /*MAC_SCH_STATS*/ + rgSCHCmnUlFreeAllocation(cell, sf, alloc); + } + /*ccpu00106104 MOD added check for AckNackRep */ + /*added check for acknack so that adaptive retx considers ue + inactivity due to ack nack repetition*/ + else if((alloc->ue != NULLP) && (TRUE != alloc->forMsg3)) + { + rgSCHCmnUlUpdAllocRetx(cell, alloc); + rgSCHUtlUlAllocRls(sf, alloc); + } + } while ((alloc = nxtAlloc) != NULLP); + + RETVOID; +} + +/** + * @brief Update an uplink subframe. + * + * @details + * + * Function : rgSCHCmnRlsUlSf + * + * For each allocation + * - if no more tx needed + * - Release allocation + * - else + * - Perform retransmission + * + * @param[in] RgSchUlSf *sf + * @param[in] U8 idx + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnRlsUlSf +( +RgSchCellCb *cell, +U8 idx +) +#else +PUBLIC Void rgSCHCmnRlsUlSf(cell, idx) +RgSchCellCb *cell; +U8 idx; +#endif +{ + TRC2(rgSCHCmnRlsUlSf); + + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + + if (cellUl->hqFdbkIdx[idx] != RGSCH_INVALID_INFO) + { + RgSchUlSf *oldSf = &cellUl->ulSfArr[cellUl->hqFdbkIdx[idx]]; + + /* Initialize the reTxLst of UL HqProcs for RETX subframe */ + if (rgSCHUtlUlAllocFirst(oldSf) == NULLP) + { + RETVOID; + } + /* Release all completed TX allocs from sf */ + rgSCHCmnUlRmvCmpltdAllocs(cell, oldSf); + + oldSf->numACqiCount = 0; + } + RETVOID; +} + +/** + * @brief Handle uplink allocation for retransmission. + * + * @details + * + * Function : rgSCHCmnUlUpdAllocRetx + * + * - Perform adaptive retransmission + * + * @param[in] RgSchUlSf *sf + * @param[in] RgSchUlAlloc *alloc + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlUpdAllocRetx +( +RgSchCellCb *cell, +RgSchUlAlloc *alloc +) +#else +PRIVATE Void rgSCHCmnUlUpdAllocRetx(cell, alloc) +RgSchCellCb *cell; +RgSchUlAlloc *alloc; +#endif +{ + RgSchCmnUlCell *cmnUlCell = RG_SCH_CMN_GET_UL_CELL(cell); + + TRC2(rgSCHCmnUlUpdAllocRetx); + + alloc->hqProc->reTxAlloc.rnti = alloc->rnti; + alloc->hqProc->reTxAlloc.numSb = alloc->numSb; + alloc->hqProc->reTxAlloc.iMcs = alloc->grnt.iMcs; +#ifdef RG_5GTF + alloc->hqProc->reTxAlloc.dciFrmt = alloc->grnt.dciFrmt; + alloc->hqProc->reTxAlloc.numLyr = alloc->grnt.numLyr; + alloc->hqProc->reTxAlloc.vrbgStart = alloc->grnt.vrbgStart; + alloc->hqProc->reTxAlloc.numVrbg = alloc->grnt.numVrbg; + alloc->hqProc->reTxAlloc.modOdr = alloc->grnt.modOdr; +#endif + //iTbs = rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs); + //iTbs = alloc->grnt.iMcs; + //RGSCH_ARRAY_BOUND_CHECK( 0, rgTbSzTbl[0], iTbs); + alloc->hqProc->reTxAlloc.tbSz = alloc->grnt.datSz; + //rgTbSzTbl[0][iTbs][alloc->grnt.numRb-1]/8; + alloc->hqProc->reTxAlloc.ue = alloc->ue; + alloc->hqProc->reTxAlloc.forMsg3 = alloc->forMsg3; + alloc->hqProc->reTxAlloc.raCb = alloc->raCb; + + /* Set as retransmission is pending */ + alloc->hqProc->isRetx = TRUE; + alloc->hqProc->alloc = NULLP; + alloc->hqProc->ulSfIdx = RGSCH_INVALID_INFO; +#ifdef UL_ADPT_DBG + printf("Adding Harq Proc Id in the retx list hqProcId %d \n",alloc->grnt.hqProcId); +#endif + cmLListAdd2Tail(&cmnUlCell->reTxLst, &alloc->hqProc->reTxLnk); + alloc->hqProc->reTxLnk.node = (PTR)alloc->hqProc; + RETVOID; +} + +/** + * @brief Attempts allocation for msg3s for which ADAP retransmissions + * are required. + * + * @details + * + * Function : rgSCHCmnUlAdapRetxAlloc + * + * Attempts allocation for msg3s for which ADAP retransmissions + * are required. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *sf + * @param[in] RgSchUlHqProcCb *proc; + * @param[in] RgSchUlHole *hole; + * @return U8 + **/ +#ifdef ANSI +PRIVATE Bool rgSCHCmnUlAdapRetxAlloc +( +RgSchCellCb *cell, +RgSchUlSf *sf, +RgSchUlHqProcCb *proc, +RgSchUlHole *hole +) +#else +PRIVATE Bool rgSCHCmnUlAdapRetxAlloc(cell, sf, proc, hole) +RgSchCellCb *cell; +RgSchUlSf *sf; +RgSchUlHqProcCb *proc; +RgSchUlHole *hole; +#endif +{ + U8 numSb = proc->reTxAlloc.numSb; + U8 iMcs = proc->reTxAlloc.iMcs; + CmLteTimingInfo frm = cell->crntTime; + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + RgSchDlSf *dlSf; + RgSchPdcch *pdcch; + RgSchUlAlloc *alloc; + TRC2(rgSCHCmnUlAdapRetxAlloc); + + /* Fetch PDCCH for msg3 */ + /* ccpu00116293 - Correcting relation between UL subframe and DL subframe based on RG_UL_DELTA*/ + /* Introduced timing delta for UL control */ + RGSCH_INCR_SUB_FRAME(frm, TFU_ULCNTRL_DLDELTA); + dlSf = rgSCHUtlSubFrmGet(cell, frm); + pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf); + if (pdcch == NULLP) + { + RETVALUE(FALSE); + } + + /* Fetch UL Alloc for msg3 */ + if (numSb <= hole->num) + { + alloc = rgSCHUtlUlAllocGetHole(sf, numSb, hole); + + /* KWork fix */ + if(alloc == NULLP) + { + rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch); + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "UL Alloc fail for msg3 retx for rnti: %d\n", + proc->reTxAlloc.rnti); + RETVALUE(FALSE); + } + + rgSCHCmnUlAllocFillRbInfo(cell, sf, alloc); + alloc->grnt.iMcs = iMcs; + alloc->grnt.datSz = proc->reTxAlloc.tbSz; +#ifdef RG_5GTF +#else + //RG_SCH_UL_MCS_TO_MODODR(iMcs, alloc->grnt.modOdr); +#endif + /* Fill UL Alloc for msg3 */ + /* RACHO : setting nDmrs to 0 and UlDelaybit to 0*/ + alloc->grnt.nDmrs = 0; + alloc->grnt.hop = 0; + alloc->grnt.delayBit = 0; + alloc->grnt.isRtx = TRUE; + proc->ulSfIdx = cellUl->schdIdx; +#ifdef RG_5GTF + proc->schdTime = cellUl->schdTime; + alloc->grnt.hqProcId = proc->procId; + alloc->grnt.dciFrmt = proc->reTxAlloc.dciFrmt; + alloc->grnt.numLyr = proc->reTxAlloc.numLyr; + alloc->grnt.vrbgStart = proc->reTxAlloc.vrbgStart; + alloc->grnt.numVrbg = proc->reTxAlloc.numVrbg; + alloc->grnt.rbAssign = rgSCHCmnCalcRiv(MAX_5GTF_VRBG, alloc->grnt.vrbgStart, alloc->grnt.numVrbg); + alloc->grnt.modOdr = proc->reTxAlloc.modOdr; + + /* TODO : Hardcoding these as of now */ + alloc->grnt.hop = 0; + alloc->grnt.SCID = 0; + alloc->grnt.xPUSCHRange = MAX_5GTF_XPUSCH_RANGE; + alloc->grnt.PMI = 0; + alloc->grnt.uciOnxPUSCH = 0; +#endif + alloc->rnti = proc->reTxAlloc.rnti; + /* Fix : syed HandIn Ue has forMsg3 and ue Set, but no RaCb */ + alloc->ue = proc->reTxAlloc.ue; + alloc->pdcch = pdcch; + alloc->forMsg3 = proc->reTxAlloc.forMsg3; + alloc->raCb = proc->reTxAlloc.raCb; + alloc->hqProc = proc; + alloc->isAdaptive = TRUE; +#ifdef LTE_L2_MEAS + sf->totPrb += alloc->grnt.numRb; +#endif + /* FIX : syed HandIn Ue has forMsg3 and ue Set, but no RaCb */ + if (alloc->raCb) + { + alloc->raCb->msg3Grnt= alloc->grnt; +#ifndef LTE_TDD + /* To the crntTime, add the time at which UE will + * actually send MSG3 */ + alloc->raCb->msg3AllocTime = cell->crntTime; + RGSCH_INCR_SUB_FRAME(alloc->raCb->msg3AllocTime, RG_SCH_CMN_MIN_RETXMSG3_RECP_INTRVL); +#else + alloc->raCb->msg3AllocTime = cellUl->schdTime; +#endif + rgSCHCmnUlAdapRetx(alloc, proc); + /* Fill PDCCH with alloc info */ + pdcch->rnti = alloc->rnti; + pdcch->dci.dciFormat = TFU_DCI_FORMAT_0; + pdcch->dci.u.format0Info.hoppingEnbld = alloc->grnt.hop; + pdcch->dci.u.format0Info.rbStart = alloc->grnt.rbStart; + pdcch->dci.u.format0Info.numRb = alloc->grnt.numRb; + pdcch->dci.u.format0Info.mcs = alloc->grnt.iMcsCrnt; + pdcch->dci.u.format0Info.ndi = alloc->hqProc->ndi; + pdcch->dci.u.format0Info.nDmrs = alloc->grnt.nDmrs; + pdcch->dci.u.format0Info.tpcCmd = alloc->grnt.tpc; + +#ifdef LTE_TDD +#ifdef TFU_TDD + /* ulIdx setting for cfg 0 shall be appropriately fixed thru ccpu00109015 */ + pdcch->dci.u.format0Info.ulIdx = RG_SCH_ULIDX_MSB; + pdcch->dci.u.format0Info.dai = RG_SCH_MAX_DAI_IDX; +#endif +#endif + pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_0]; + } + else + { + RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(alloc->ue,cell); +#ifdef TFU_UPGRADE + alloc->ue->initNumRbs = (alloc->grnt.numVrbg * MAX_5GTF_VRBG_SIZE); +#endif +#ifdef LTE_L2_MEAS + ue->ul.nPrb = alloc->grnt.numRb; +#endif + ueUl->alloc.alloc = alloc; + /* FIx: Removed the call to rgSCHCmnUlAdapRetx */ + rgSCHCmnUlUeFillAllocInfo(cell, alloc->ue); + /* Setting csireq as false for Adaptive Retx*/ + ueUl->alloc.alloc->pdcch->dci.u.format0Info.cqiReq = RG_SCH_APCQI_NO; + pdcch->dciNumOfBits = alloc->ue->dciSize.cmnSize[TFU_DCI_FORMAT_0]; + } + /* Reset as retransmission is done */ + proc->isRetx = FALSE; + } + else /* Intg fix */ + { + rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch); + RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId, + "Num SB not suffiecient for adap retx for rnti: %d", + proc->reTxAlloc.rnti); + RETVALUE(FALSE); + } + RETVALUE(TRUE); +} + +/* Fix: syed Adaptive Msg3 Retx crash. */ +/** + * @brief Releases all Adaptive Retx HqProcs which failed for + * allocations in this scheduling occassion. + * + * @details + * + * Function : rgSCHCmnUlSfRlsRetxProcs + * + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *sf + * @return U8 + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlSfRlsRetxProcs +( +RgSchCellCb *cell, +RgSchUlSf *sf +) +#else +PRIVATE Void rgSCHCmnUlSfRlsRetxProcs(cell, sf) +RgSchCellCb *cell; +RgSchUlSf *sf; +#endif +{ + CmLListCp *cp; + CmLList *node; + RgSchUlHqProcCb *proc; + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + + TRC2(rgSCHCmnUlSfRlsRetxProcs); + + cp = &(cellUl->reTxLst); + node = cp->first; + while (node) + { + proc = (RgSchUlHqProcCb *)node->node; + node = node->next; + /* ccpu00137834 : Deleting reTxLnk from the respective reTxLst */ + cmLListDelFrm(&cellUl->reTxLst, &proc->reTxLnk); + proc->reTxLnk.node = (PTR)NULLP; + } + RETVOID; +} + + +/** + * @brief Attempts allocation for UEs for which retransmissions + * are required. + * + * @details + * + * Function : rgSCHCmnUlSfReTxAllocs + * + * Attempts allocation for UEs for which retransmissions + * are required. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUlSf *sf + * @return U8 + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnUlSfReTxAllocs +( +RgSchCellCb *cell, +RgSchUlSf *sf +) +#else +PRIVATE Void rgSCHCmnUlSfReTxAllocs(cell, sf) +RgSchCellCb *cell; +RgSchUlSf *sf; +#endif +{ + CmLListCp *cp; + CmLList *node; + RgSchUlHqProcCb *proc; + RgSchUlHole *hole; + RgSchUeCb *ue; + RgSchCmnCell *schCmnCell = (RgSchCmnCell *)(cell->sc.sch); + RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell); + TRC2(rgSCHCmnUlSfReTxAllocs); + + cp = &(cellUl->reTxLst); + node = cp->first; + while ((node)) + { + proc = (RgSchUlHqProcCb *)node->node; + ue = proc->reTxAlloc.ue; + node = node->next; + /*ccpu00106104 MOD added check for AckNackRep */ + /*added check for acknack so that adaptive retx considers ue + inactivity due to ack nack repetition*/ + if((ue != NULLP) && + ((ue->measGapCb.isMeasuring == TRUE)|| + (ue->ackNakRepCb.isAckNakRep == TRUE))) + { + continue; + } + /* Fix for ccpu00123917: Check if maximum allocs per UL sf have been exhausted */ + if (((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP) + || (sf->allocDb->count == schCmnCell->ul.maxAllocPerUlSf)) + { + /* No more UL BW then return */ + break; + } + /* perform adaptive retx for UE's */ + if (rgSCHCmnUlAdapRetxAlloc(cell, sf, proc, hole) == FALSE) + { + continue; + } + /* ccpu00137834 : Deleting reTxLnk from the respective reTxLst */ + cmLListDelFrm(&cellUl->reTxLst, &proc->reTxLnk); + /* Fix: syed Adaptive Msg3 Retx crash. */ + proc->reTxLnk.node = (PTR)NULLP; + } + RETVOID; +} + +/** + * @brief Handles RB allocation for downlink. + * + * @details + * + * Function : rgSCHCmnDlRbAlloc + * + * Invoking Module Processing: + * - This function is invoked for DL RB allocation + * + * Processing Steps: + * - If cell is frequency selecive, + * - Call rgSCHDlfsAllocRb(). + * - else, + * - Call rgSCHCmnNonDlfsRbAlloc(). + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlRbAllocInfo *allocInfo + * @return Void + **/ + +#ifdef ANSI +PRIVATE Void rgSCHCmnDlRbAlloc +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnDlRbAlloc(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + TRC2(rgSCHCmnDlRbAlloc); + + if (cellSch->dl.isDlFreqSel) + { + printf("5GTF_ERROR DLFS SCH Enabled\n"); + cellSch->apisDlfs->rgSCHDlfsAllocRb(cell, allocInfo); + } + else + { + rgSCHCmnNonDlfsRbAlloc(cell, allocInfo); + } + RETVOID; +} + +#ifdef LTEMAC_SPS + +/** + * @brief Determines number of RBGs and RBG subset sizes for the given DL + * bandwidth and rbgSize + * + * @details + * Function : rgSCHCmnDlGetRbgInfo + * + * + * Processing Steps: + * - Fill-up rbgInfo data structure for given DL bandwidth and rbgSize + * + * @param[in] U8 dlTotalBw + * @param[in] U8 dlSubsetBw + * @param[in] U8 maxRaType1SubsetBw + * @param[in] U8 rbgSize + * @param[out] RgSchBwRbgInfo *rbgInfo + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlGetRbgInfo +( +U8 dlTotalBw, +U8 dlSubsetBw, +U8 maxRaType1SubsetBw, +U8 rbgSize, +RgSchBwRbgInfo *rbgInfo +) +#else +PUBLIC Void rgSCHCmnDlGetRbgInfo(dlTotalBw, dlSubsetBw, maxRaType1SubsetBw, + rbgSize, rbgInfo) +U8 dlTotalBw; +U8 dlSubsetBw; +U8 maxRaType1SubsetBw; +U8 rbgSize; +RgSchBwRbgInfo *rbgInfo; +#endif +{ +#ifdef RGSCH_SPS_UNUSED + U8 idx = 0; + U8 lastRbgIdx = ((dlTotalBw + rbgSize - 1)/rbgSize) - 1; + U8 currRbgSize = rbgSize; + U8 subsetSizeIdx = 0; + U8 subsetSize[RG_SCH_NUM_RATYPE1_SUBSETS] = {0}; + U8 lastRbgSize = rbgSize - (dlTotalBw - ((dlTotalBw/rbgSize) * rbgSize)); + U8 numRaType1Rbgs = (maxRaType1SubsetBw + rbgSize - 1)/rbgSize; +#endif + + /* Compute maximum number of SPS RBGs for the cell */ + rbgInfo->numRbgs = ((dlSubsetBw + rbgSize - 1)/rbgSize); + +#ifdef RGSCH_SPS_UNUSED + /* Distribute RBGs across subsets except last RBG */ + for (;idx < numRaType1Rbgs - 1; ++idx) + { + subsetSize[subsetSizeIdx] += currRbgSize; + subsetSizeIdx = (subsetSizeIdx + 1) % rbgSize; + } + + /* Computation for last RBG */ + if (idx == lastRbgIdx) + { + currRbgSize = lastRbgSize; + } + subsetSize[subsetSizeIdx] += currRbgSize; + subsetSizeIdx = (subsetSizeIdx + 1) % rbgSize; +#endif + + /* Update the computed sizes */ +#ifdef RGSCH_SPS_UNUSED + rbgInfo->lastRbgSize = currRbgSize; +#endif + rbgInfo->lastRbgSize = rbgSize - + (dlSubsetBw - ((dlSubsetBw/rbgSize) * rbgSize)); +#ifdef RGSCH_SPS_UNUSED + cmMemcpy((U8 *)rbgInfo->rbgSubsetSize, (U8 *) subsetSize, 4 * sizeof(U8)); +#endif + rbgInfo->numRbs = (rbgInfo->numRbgs * rbgSize > dlTotalBw) ? + dlTotalBw:(rbgInfo->numRbgs * rbgSize); + rbgInfo->rbgSize = rbgSize; +} + +/** + * @brief Handles RB allocation for Resource allocation type 0 + * + * @details + * + * Function : rgSCHCmnDlRaType0Alloc + * + * Invoking Module Processing: + * - This function is invoked for DL RB allocation for resource allocation + * type 0 + * + * Processing Steps: + * - Determine the available positions in the rbgMask. + * - Allocate RBGs in the available positions. + * - Update RA Type 0, RA Type 1 and RA type 2 masks. + * + * @param[in] RgSchDlSfAllocInfo *allocedInfo + * @param[in] U8 rbsReq + * @param[in] RgSchBwRbgInfo *rbgInfo + * @param[out] U8 *numAllocRbs + * @param[out] RgSchDlSfAllocInfo *resAllocInfo + * @param[in] Bool isPartialAlloc + * + * @return Void + **/ + +#ifdef ANSI +PUBLIC U8 rgSCHCmnDlRaType0Alloc +( +RgSchDlSfAllocInfo *allocedInfo, +U8 rbsReq, +RgSchBwRbgInfo *rbgInfo, +U8 *numAllocRbs, +RgSchDlSfAllocInfo *resAllocInfo, +Bool isPartialAlloc +) +#else +PUBLIC U8 rgSCHCmnDlRaType0Alloc(allocedInfo, rbsReq, rbgInfo, + numAllocRbs, resAllocInfo, isPartialAlloc) +RgSchDlSfAllocInfo *allocedInfo; +U8 rbsReq; +RgSchBwRbgInfo *rbgInfo; +U8 *numAllocRbs; +RgSchDlSfAllocInfo *resAllocInfo; +Bool isPartialAlloc; +#endif +{ + /* Note: This function atttempts allocation only full allocation */ + U32 remNumRbs, rbgPosInRbgMask, ueRaType2Mask; + U8 type2MaskIdx, cnt, rbIdx; + U8 maskSize, rbg; + U8 bestNumAvailRbs = 0; + U8 usedRbs = 0; + U8 numAllocRbgs = 0; + U8 rbgSize = rbgInfo->rbgSize; + U32 *rbgMask = &(resAllocInfo->raType0Mask); +#ifdef RGSCH_SPS_UNUSED + U8 rbgSubset; + U32 ueRaType1Mask; + U32 *raType1Mask = resAllocInfo->raType1Mask; + U32 *raType1UsedRbs = resAllocInfo->raType1UsedRbs; +#endif + U32 *raType2Mask = resAllocInfo->raType2Mask; + + U32 allocedMask = allocedInfo->raType0Mask; + + maskSize = rbgInfo->numRbgs; + + *numAllocRbs = 0; + RG_SCH_CMN_DL_COUNT_ONES(allocedMask, maskSize, &usedRbs); + if (maskSize == usedRbs) + { + /* All RBGs are allocated, including the last one */ + remNumRbs = 0; + } + else + { + remNumRbs = (maskSize - usedRbs - 1) * rbgSize; /* vamsee: removed minus 1 */ + + /* If last RBG is available, add last RBG size */ + if (!(allocedMask & (1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(maskSize - 1)))) + { + remNumRbs += rbgInfo->lastRbgSize; + } + } + + /* If complete allocation is needed, check if total requested RBs are available else + * check the best available RBs */ + if (!isPartialAlloc) + { + if (remNumRbs >= rbsReq) + { + bestNumAvailRbs = rbsReq; + } + } + else + { + bestNumAvailRbs = remNumRbs > rbsReq ? rbsReq : remNumRbs; + } + + /* Allocate for bestNumAvailRbs */ + if (bestNumAvailRbs) + { + for (rbg = 0; rbg < maskSize - 1; ++rbg) + { + rbgPosInRbgMask = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbg); + if (!(allocedMask & rbgPosInRbgMask)) + { + /* Update RBG mask */ + *rbgMask |= rbgPosInRbgMask; + + /* Compute RB index of the first RB of the RBG allocated */ + rbIdx = rbg * rbgSize; + + for (cnt = 0; cnt < rbgSize; ++cnt) + { +#ifdef RGSCH_SPS_UNUSED + ueRaType1Mask = rgSCHCmnGetRaType1Mask(rbIdx, rbgSize, &rbgSubset); +#endif + ueRaType2Mask = rgSCHCmnGetRaType2Mask(rbIdx, &type2MaskIdx); +#ifdef RGSCH_SPS_UNUSED + /* Update RBG mask for RA type 1 */ + raType1Mask[rbgSubset] |= ueRaType1Mask; + raType1UsedRbs[rbgSubset]++; +#endif + /* Update RA type 2 mask */ + raType2Mask[type2MaskIdx] |= ueRaType2Mask; + rbIdx++; + } + *numAllocRbs += rbgSize; + remNumRbs -= rbgSize; + ++numAllocRbgs; + if (*numAllocRbs >= bestNumAvailRbs) + { + break; + } + } + } + /* If last RBG available and allocation is not completed, allocate + * last RBG */ + if (*numAllocRbs < bestNumAvailRbs) + { + rbgPosInRbgMask = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbg); + *rbgMask |= rbgPosInRbgMask; + *numAllocRbs += rbgInfo->lastRbgSize; + + /* Compute RB index of the first RB of the last RBG */ + rbIdx = ((rbgInfo->numRbgs - 1 ) * rbgSize ); /* removed minus 1 vamsee */ + + for (cnt = 0; cnt < rbgInfo->lastRbgSize; ++cnt) + { +#ifdef RGSCH_SPS_UNUSED + ueRaType1Mask = rgSCHCmnGetRaType1Mask(rbIdx, rbgSize, &rbgSubset); +#endif + ueRaType2Mask = rgSCHCmnGetRaType2Mask(rbIdx, &type2MaskIdx); +#ifdef RGSCH_SPS_UNUSED + /* Update RBG mask for RA type 1 */ + raType1Mask[rbgSubset] |= ueRaType1Mask; + raType1UsedRbs[rbgSubset]++; +#endif + /* Update RA type 2 mask */ + raType2Mask[type2MaskIdx] |= ueRaType2Mask; + rbIdx++; + } + remNumRbs -= rbgInfo->lastRbgSize; + ++numAllocRbgs; + } + /* Note: this should complete allocation, not checking for the + * same */ + } + + RETVALUE(numAllocRbgs); +} + +#ifdef RGSCH_SPS_UNUSED +/** + * @brief Handles RB allocation for Resource allocation type 1 + * + * @details + * + * Function : rgSCHCmnDlRaType1Alloc + * + * Invoking Module Processing: + * - This function is invoked for DL RB allocation for resource allocation + * type 1 + * + * Processing Steps: + * - Determine the available positions in the subsets. + * - Allocate RB in the available subset. + * - Update RA Type1, RA type 0 and RA type 2 masks. + * + * @param[in] RgSchDlSfAllocInfo *allocedInfo + * @param[in] U8 rbsReq + * @param[in] RgSchBwRbgInfo *rbgInfo + * @param[in] U8 startRbgSubset + * @param[in] U8 *allocRbgSubset + * @param[out] rgSchDlSfAllocInfo *resAllocInfo + * @param[in] Bool isPartialAlloc + * + * @return U8 + * Number of allocated RBs + **/ + +#ifdef ANSI +PUBLIC U8 rgSCHCmnDlRaType1Alloc +( +RgSchDlSfAllocInfo *allocedInfo, +U8 rbsReq, +RgSchBwRbgInfo *rbgInfo, +U8 startRbgSubset, +U8 *allocRbgSubset, +RgSchDlSfAllocInfo *resAllocInfo, +Bool isPartialAlloc +) +#else +PUBLIC U8 rgSCHCmnDlRaType1Alloc(allocedInfo, rbsReq,rbgInfo,startRbgSubset, + allocRbgSubset, resAllocInfo, isPartialAlloc) +RgSchDlSfAllocInfo *allocedInfo; +U8 rbsReq; +RgSchBwRbgInfo *rbgInfo; +U8 startRbgSubset; +U8 *allocRbgSubset; +RgSchDlSfAllocInfo *resAllocInfo; +Bool isPartialAlloc; +#endif +{ + /* Note: This function atttempts only full allocation */ + U8 *rbgSubsetSzArr; + U8 type2MaskIdx, subsetIdx, rbIdx, rbInSubset, rbgInSubset; + U8 offset, rbg, maskSize, bestSubsetIdx; + U8 startPos = 0; + U8 bestNumAvailRbs = 0; + U8 numAllocRbs = 0; + U32 ueRaType2Mask, ueRaType0Mask, rbPosInSubset; + U32 remNumRbs, allocedMask; + U8 usedRbs = 0; + U8 rbgSize = rbgInfo->rbgSize; + U8 rbgSubset = startRbgSubset; + U32 *rbgMask = &resAllocInfo->raType0Mask; + U32 *raType1Mask = resAllocInfo->raType1Mask; + U32 *raType2Mask = resAllocInfo->raType2Mask; + U32 *raType1UsedRbs = resAllocInfo->raType1UsedRbs; + U32 *allocMask = allocedInfo->raType1Mask; + + /* Initialize the subset size Array */ + rbgSubsetSzArr = rbgInfo->rbgSubsetSize; + + /* Perform allocation for RA type 1 */ + for (subsetIdx = 0;subsetIdx < rbgSize; ++subsetIdx) + { + allocedMask = allocMask[rbgSubset]; + maskSize = rbgSubsetSzArr[rbgSubset]; + + /* Determine number of available RBs in the subset */ + usedRbs = allocedInfo->raType1UsedRbs[subsetIdx]; + remNumRbs = maskSize - usedRbs; + + if (remNumRbs >= rbsReq) + { + bestNumAvailRbs = rbsReq; + bestSubsetIdx = rbgSubset; + break; + } + else if (isPartialAlloc && (remNumRbs > bestNumAvailRbs)) + { + bestNumAvailRbs = remNumRbs; + bestSubsetIdx = rbgSubset; + } + + rbgSubset = (rbgSubset + 1) % rbgSize; + } /* End of for (each rbgsubset) */ + + if (bestNumAvailRbs) + { + /* Initialize alloced mask and subsetSize depending on the RBG + * subset of allocation */ + U8 startIdx = 0; + maskSize = rbgSubsetSzArr[bestSubsetIdx]; + allocedMask = allocMask[bestSubsetIdx]; + RG_SCH_CMN_DL_GET_START_POS(allocedMask, maskSize, + &startPos); + for (; startIdx < rbgSize; ++startIdx, ++startPos) + { + for (rbInSubset = startPos; rbInSubset < maskSize; + rbInSubset = rbInSubset + rbgSize) + { + rbPosInSubset = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbInSubset); + if (!(allocedMask & rbPosInSubset)) + { + raType1Mask[bestSubsetIdx] |= rbPosInSubset; + raType1UsedRbs[bestSubsetIdx]++; + + /* Compute RB index value for the RB being allocated */ + rbgInSubset = rbInSubset /rbgSize; + offset = rbInSubset % rbgSize; + rbg = (rbgInSubset * rbgSize) + bestSubsetIdx; + rbIdx = (rbg * rbgSize) + offset; + + /* Update RBG mask for RA type 0 allocation */ + ueRaType0Mask = rgSCHCmnGetRaType0Mask(rbIdx, rbgSize); + *rbgMask |= ueRaType0Mask; + + /* Update RA type 2 mask */ + ueRaType2Mask = rgSCHCmnGetRaType2Mask(rbIdx, &type2MaskIdx); + raType2Mask[type2MaskIdx] |= ueRaType2Mask; + + /* Update the counters */ + numAllocRbs++; + remNumRbs--; + if (numAllocRbs == bestNumAvailRbs) + { + break; + } + } + } /* End of for (each position in the subset mask) */ + if (numAllocRbs == bestNumAvailRbs) + { + break; + } + } /* End of for startIdx = 0 to rbgSize */ + + *allocRbgSubset = bestSubsetIdx; + } /* End of if (bestNumAvailRbs) */ + + RETVALUE(numAllocRbs); +} +#endif +/** + * @brief Handles RB allocation for Resource allocation type 2 + * + * @details + * + * Function : rgSCHCmnDlRaType2Alloc + * + * Invoking Module Processing: + * - This function is invoked for DL RB allocation for resource allocation + * type 2 + * + * Processing Steps: + * - Determine the available positions in the mask + * - Allocate best fit cosecutive RBs. + * - Update RA Type2, RA type 1 and RA type 0 masks. + * + * @param[in] RgSchDlSfAllocInfo *allocedInfo + * @param[in] U8 rbsReq + * @param[in] RgSchBwRbgInfo *rbgInfo + * @param[out] U8 *rbStart + * @param[out] rgSchDlSfAllocInfo *resAllocInfo + * @param[in] Bool isPartialAlloc + * + * @return U8 + * Number of allocated RBs + **/ + +#ifdef ANSI +PUBLIC U8 rgSCHCmnDlRaType2Alloc +( +RgSchDlSfAllocInfo *allocedInfo, +U8 rbsReq, +RgSchBwRbgInfo *rbgInfo, +U8 *rbStart, +RgSchDlSfAllocInfo *resAllocInfo, +Bool isPartialAlloc +) +#else +PUBLIC U8 rgSCHCmnDlRaType2Alloc(allocedInfo, rbsReq, rbgInfo, rbStart, + resAllocInfo, isPartialAlloc) +RgSchDlSfAllocInfo *allocedInfo; +U8 rbsReq; +RgSchBwRbgInfo *rbgInfo; +U8 *rbStart; +RgSchDlSfAllocInfo *resAllocInfo; +Bool isPartialAlloc; +#endif +{ + U8 numAllocRbs = 0; + U8 rbIdx; + U8 rbgSize = rbgInfo->rbgSize; + U32 *rbgMask = &resAllocInfo->raType0Mask; +#ifdef RGSCH_SPS_UNUSED + U32 *raType1Mask = resAllocInfo->raType1Mask; +#endif + U32 *raType2Mask = resAllocInfo->raType2Mask; +#ifdef RGSCH_SPS_UNUSED + U32 *raType1UsedRbs = resAllocInfo->raType1UsedRbs; +#endif + U32 *allocedMask = allocedInfo->raType2Mask; + + /* Note: This function atttempts only full allocation */ + rgSCHCmnDlGetBestFitHole(allocedMask, rbgInfo->numRbs, + raType2Mask, rbsReq, rbStart, &numAllocRbs, isPartialAlloc); + if (numAllocRbs) + { + /* Update the allocation in RA type 0 and RA type 1 masks */ + U8 rbCnt = numAllocRbs; +#ifdef RGSCH_SPS_UNUSED + U8 rbgSubset; + U32 ueRaType1Mask; +#endif + U32 ueRaType0Mask; + rbIdx = *rbStart; + + while(rbCnt) + { + /* Update RBG mask for RA type 0 allocation */ + ueRaType0Mask = rgSCHCmnGetRaType0Mask(rbIdx, rbgSize); + *rbgMask |= ueRaType0Mask; + +#ifdef RGSCH_SPS_UNUSED + /* Update RBG mask for RA type 1 */ + ueRaType1Mask = rgSCHCmnGetRaType1Mask(rbIdx, rbgSize, &rbgSubset); + raType1Mask[rbgSubset] |= ueRaType1Mask; + raType1UsedRbs[rbgSubset]++; +#endif + /* Update the counters */ + --rbCnt; + rbIdx++; + } + } + + RETVALUE(numAllocRbs); +} + +/** + * @brief Determines RA type 0 mask from given RB index. + * + * @details + * + * Function : rgSCHCmnGetRaType0Mask + * + * + * Processing Steps: + * - Determine RA Type 0 mask for given rbIdex and rbg size. + * + * @param[in] U8 rbIdx + * @param[in] U8 rbgSize + * @return U32 RA type 0 mask + **/ +#ifdef ANSI +PRIVATE U32 rgSCHCmnGetRaType0Mask +( +U8 rbIdx, +U8 rbgSize +) +#else +PRIVATE U32 rgSCHCmnGetRaType0Mask(rbIdx, rbgSize) +U8 rbIdx; +U8 rbgSize; +#endif +{ + U8 rbg; + U32 rbgPosInRbgMask = 0; + + rbg = rbIdx/rbgSize; + rbgPosInRbgMask = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbg); + + RETVALUE(rbgPosInRbgMask); +} + +#ifdef RGSCH_SPS_UNUSED +/** + * @brief Determines RA type 1 mask from given RB index. + * + * @details + * + * Function : rgSCHCmnGetRaType1Mask + * + * + * Processing Steps: + * - Determine RA Type 1 mask for given rbIdex and rbg size. + * + * @param[in] U8 rbIdx + * @param[in] U8 rbgSize + * @param[out] U8 *type1Subset + * @return U32 RA type 1 mask + **/ +#ifdef ANSI +PRIVATE U32 rgSCHCmnGetRaType1Mask +( +U8 rbIdx, +U8 rbgSize, +U8 *type1Subset +) +#else +PRIVATE U32 rgSCHCmnGetRaType1Mask(rbIdx, rbgSize, type1Subset) +U8 rbIdx; +U8 rbgSize; +U8 *type1Subset; +#endif +{ + U8 rbg, rbgSubset, rbgInSubset, offset, rbInSubset; + U32 rbPosInSubset; + + rbg = rbIdx/rbgSize; + rbgSubset = rbg % rbgSize; + rbgInSubset = rbg/rbgSize; + offset = rbIdx % rbgSize; + rbInSubset = rbgInSubset * rbgSize + offset; + rbPosInSubset = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbInSubset); + + *type1Subset = rbgSubset; + RETVALUE(rbPosInSubset); +} +#endif /* RGSCH_SPS_UNUSED */ +/** + * @brief Determines RA type 2 mask from given RB index. + * + * @details + * + * Function : rgSCHCmnGetRaType2Mask + * + * + * Processing Steps: + * - Determine RA Type 2 mask for given rbIdx and rbg size. + * + * @param[in] U8 rbIdx + * @param[out] U8 *maskIdx + * @return U32 RA type 2 mask + **/ +#ifdef ANSI +PRIVATE U32 rgSCHCmnGetRaType2Mask +( +U8 rbIdx, +U8 *maskIdx +) +#else +PRIVATE U32 rgSCHCmnGetRaType2Mask(rbIdx, maskIdx) +U8 rbIdx; +U8 *maskIdx; +#endif +{ + U32 rbPosInType2; + + *maskIdx = rbIdx / 32; + rbPosInType2 = 1 << RG_SCH_CMN_DL_GET_POS_FRM_LSB(rbIdx % 32); + + RETVALUE(rbPosInType2); +} + +/** + * @brief Performs resource allocation for a non-SPS UE in SPS bandwidth + * + * @details + * + * Function : rgSCHCmnAllocUeInSpsBw + * + * + * Processing Steps: + * - Determine allocation for the UE. + * - Use resource allocation type 0, 1 and 2 for allocation + * within maximum SPS bandwidth. + * + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlRbAlloc *rbAllocInfo + * @param[in] Bool isPartialAlloc + * @return Bool + * ROK success + * RFAILED failed + **/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnAllocUeInSpsBw +( +RgSchDlSf *dlSf, +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlRbAlloc *rbAllocInfo, +Bool isPartialAlloc +) +#else +PUBLIC Bool rgSCHCmnAllocUeInSpsBw(dlSf, cell, ue, rbAllocInfo, isPartialAlloc) +RgSchDlSf *dlSf; +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlRbAlloc *rbAllocInfo; +Bool isPartialAlloc; +#endif +{ + U8 rbgSize = cell->rbgSize; + U8 numAllocRbs = 0; + U8 numAllocRbgs = 0; + U8 rbStart = 0; + U8 idx, noLyr, iTbs; + RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue,cell); + RgSchDlSfAllocInfo *dlSfAlloc = &rbAllocInfo->dlSf->dlSfAllocInfo; + RgSchBwRbgInfo *spsRbgInfo = &cell->spsBwRbgInfo; + + /* SPS_FIX : Check if this Hq proc is scheduled */ + if ((0 == rbAllocInfo->tbInfo[0].schdlngForTb) && + (0 == rbAllocInfo->tbInfo[1].schdlngForTb)) + { + RETVALUE(TRUE); + } + + /* Check if the requirement can be accomodated in SPS BW */ + if (dlSf->spsAllocdBw == spsRbgInfo->numRbs) + { + /* SPS Bandwidth has been exhausted: no further allocations possible */ + RETVALUE(FALSE); + } + if (!isPartialAlloc) + { + if((dlSf->spsAllocdBw + rbAllocInfo->rbsReq) > spsRbgInfo->numRbs) + { + RETVALUE(TRUE); + } + } + + /* Perform allocation for RA type 0 if rbsReq is multiple of RBG size (also + * if RBG size = 1) */ + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + rbAllocInfo->rbsReq += (rbgSize - rbAllocInfo->rbsReq % rbgSize); + numAllocRbgs = rgSCHCmnDlRaType0Alloc(dlSfAlloc, + rbAllocInfo->rbsReq, spsRbgInfo, &numAllocRbs, + &rbAllocInfo->resAllocInfo, isPartialAlloc); + } +#ifdef RGSCH_SPS_UNUSED + else if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE1) + { + /* If no RBS could be allocated, attempt RA TYPE 1 */ + + numAllocRbs = rgSCHCmnDlRaType1Alloc(dlSfAlloc, + rbAllocInfo->rbsReq, spsRbgInfo, (U8)dlSfAlloc->nxtRbgSubset, + &rbAllocInfo->allocInfo.raType1.rbgSubset, + &rbAllocInfo->resAllocInfo, isPartialAlloc); + + if(numAllocRbs) + { + dlSfAlloc->nxtRbgSubset = + (rbAllocInfo->allocInfo.raType1.rbgSubset + 1 ) % rbgSize; + } + } +#endif + else if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + numAllocRbs = rgSCHCmnDlRaType2Alloc(dlSfAlloc, + rbAllocInfo->rbsReq, spsRbgInfo, + &rbStart, &rbAllocInfo->resAllocInfo, isPartialAlloc); + } + if (!numAllocRbs) + { + RETVALUE(TRUE); + } + + if (!(rbAllocInfo->pdcch = + rgSCHCmnPdcchAlloc(cell, ue, dlSf, dlUe->mimoInfo.cwInfo[0].cqi,\ + rbAllocInfo->dciFormat, FALSE))) + { + /* Note: Returning TRUE since PDCCH might be available for another UE */ + RETVALUE(TRUE); + } + + /* Update Tb info for each scheduled TB */ + iTbs = rbAllocInfo->tbInfo[0].iTbs; + noLyr = rbAllocInfo->tbInfo[0].noLyr; + rbAllocInfo->tbInfo[0].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][numAllocRbs - 1]/8; + + if (rbAllocInfo->tbInfo[1].schdlngForTb) + { + iTbs = rbAllocInfo->tbInfo[1].iTbs; + noLyr = rbAllocInfo->tbInfo[1].noLyr; + rbAllocInfo->tbInfo[1].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][numAllocRbs - 1]/8;; + } + + /* Update rbAllocInfo with the allocation information */ + if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + rbAllocInfo->allocInfo.raType0.dlAllocBitMask = + rbAllocInfo->resAllocInfo.raType0Mask; + rbAllocInfo->allocInfo.raType0.numDlAlloc = numAllocRbgs; + } +#ifdef RGSCH_SPS_UNUSED + else if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE1) + { + rbAllocInfo->allocInfo.raType1.dlAllocBitMask = + rbAllocInfo->resAllocInfo.raType1Mask[rbAllocInfo->allocInfo.raType1.rbgSubset]; + rbAllocInfo->allocInfo.raType1.numDlAlloc = numAllocRbs; + rbAllocInfo->allocInfo.raType1.shift = 0; + } +#endif + else if (rbAllocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + rbAllocInfo->allocInfo.raType2.isLocal = TRUE; + rbAllocInfo->allocInfo.raType2.rbStart = rbStart; + rbAllocInfo->allocInfo.raType2.numRb = numAllocRbs; + } + + rbAllocInfo->rbsAlloc = numAllocRbs; + rbAllocInfo->tbInfo[0].schdlngForTb = TRUE; + + /* Update allocation masks for RA types 0, 1 and 2 in DL SF */ + + /* Update type 0 allocation mask */ + dlSfAlloc->raType0Mask |= rbAllocInfo->resAllocInfo.raType0Mask; +#ifdef RGSCH_SPS_UNUSED + /* Update type 1 allocation masks */ + for (idx = 0; idx < RG_SCH_NUM_RATYPE1_32BIT_MASK; ++idx) + { + dlSfAlloc->raType1Mask[idx] |= rbAllocInfo->resAllocInfo.raType1Mask[idx]; + dlSfAlloc->raType1UsedRbs[idx] += + rbAllocInfo->resAllocInfo.raType1UsedRbs[idx]; + } +#endif + /* Update type 2 allocation masks */ + for (idx = 0; idx < RG_SCH_NUM_RATYPE2_32BIT_MASK; ++idx) + { + dlSfAlloc->raType2Mask[idx] |= rbAllocInfo->resAllocInfo.raType2Mask[idx]; + } + + dlSf->spsAllocdBw += numAllocRbs; + RETVALUE(TRUE); +} + +/*********************************************************** + * + * Func : rgSCHCmnDlGetBestFitHole + * + * + * Desc : Converts the best fit hole into allocation and returns the + * allocation information. + * + * + * Ret : Void + * + * + * Notes: + * + * File : + * + **********************************************************/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlGetBestFitHole +( +U32 *allocMask, +U8 numMaskRbs, +U32 *crntAllocMask, +U8 rbsReq, +U8 *allocStart, +U8 *allocNumRbs, +Bool isPartialAlloc +) +#else +PRIVATE Void rgSCHCmnDlGetBestFitHole (allocMask, numMaskRbs, + crntAllocMask, rbsReq, allocStart, allocNumRbs, isPartialAlloc) +U32 *allocMask; +U8 numMaskRbs; +U32 *crntAllocMask; +U8 rbsReq; +U8 *allocStart; +U8 *allocNumRbs; +Bool isPartialAlloc; +#endif +{ + U8 maskSz = (numMaskRbs + 31)/32; + U8 maxMaskPos = (numMaskRbs % 32); + U8 maskIdx, maskPos; + U8 numAvailRbs = 0; + U8 bestAvailNumRbs = 0; + S8 bestStartPos = -1; + S8 startPos = -1; + U32 tmpMask[RG_SCH_NUM_RATYPE2_32BIT_MASK] = {0}; + U32 bestMask[RG_SCH_NUM_RATYPE2_32BIT_MASK] = {0}; + + *allocNumRbs = numAvailRbs; + *allocStart = 0; + + for (maskIdx = 0; maskIdx < maskSz; ++maskIdx) + { + maxMaskPos = 31; + if (maskIdx == (maskSz - 1)) + { + if (numMaskRbs % 32) + { + maxMaskPos = numMaskRbs % 32; + } + } + for (maskPos = 0; maskPos < maxMaskPos; ++maskPos) + { + if (!(allocMask[maskIdx] & (1 << (31 - maskPos)))) + { + tmpMask[maskIdx] |= (1 << (31 - maskPos)); + if (startPos == -1) + { + startPos = maskIdx * 32 + maskPos; + } + ++numAvailRbs; + if (numAvailRbs == rbsReq) + { + *allocStart = (U8)startPos; + *allocNumRbs = rbsReq; + break; + } + } + else + { + if (numAvailRbs > bestAvailNumRbs) + { + bestAvailNumRbs = numAvailRbs; + bestStartPos = startPos; + cmMemcpy((U8 *)bestMask, (U8 *) tmpMask, 4 * sizeof(U32)); + } + numAvailRbs = 0; + startPos = -1; + cmMemset((U8 *)tmpMask, 0, 4 * sizeof(U32)); + } + } + if (*allocNumRbs == rbsReq) + { + break; + } + } + + if (*allocNumRbs == rbsReq) + { + /* Convert the hole into allocation */ + cmMemcpy((U8 *)crntAllocMask, (U8 *) tmpMask, 4 * sizeof(U32)); + RETVOID; + } + else + { + if (bestAvailNumRbs && isPartialAlloc) + { + /* Partial allocation could have been done */ + *allocStart = (U8)bestStartPos; + *allocNumRbs = bestAvailNumRbs; + /* Convert the hole into allocation */ + cmMemcpy((U8 *)crntAllocMask, (U8 *) bestMask, 4 * sizeof(U32)); + } + } + + RETVOID; +} +#endif /* LTEMAC_SPS */ + +/*************************************************************************** + * + * NON-DLFS Allocation functions + * + * *************************************************************************/ +#ifndef LTE_TDD +#ifdef DEBUGP +/** + * @brief Function to find out code rate + * + * @details + * + * Function : rgSCHCmnFindCodeRate + * + * Processing Steps: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @return void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFindCodeRate +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +U8 idx +) +#else +PRIVATE Void rgSCHCmnFindCodeRate(cell,dlSf,allocInfo,idx) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +U8 idx; +#endif +{ + RETVOID; + +} +#endif + +/* Adjust the Imcs and bytes allocated also with respect to the adjusted + RBs - Here we will find out the Imcs by identifying first Highest + number of bits compared to the original bytes allocated. */ +/** + * @brief Adjust IMCS according to tbSize and ITBS + * + * @details + * + * Function : rgSCHCmnNonDlfsPbchTbImcsAdj + * + * Processing Steps: + * - Adjust Imcs according to tbSize and ITBS. + * + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @param[in] U8 *idx + * @return void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsPbchTbImcsAdj +( +RgSchCellCb *cell, +RgSchDlRbAlloc *allocInfo, +U8 idx, +U8 rbsReq +) +#else +PRIVATE Void rgSCHCmnNonDlfsPbchTbImcsAdj(cell,allocInfo, idx, rbsReq) +RgSchCellCb *cell; +RgSchDlRbAlloc *allocInfo; +U8 idx; +U8 rbsReq; +#endif +{ + U8 noLyrs = 0; + U8 tbs = 0; + U32 origBytesReq; + U8 noRbgs = 0; + U8 noRbs = 0; + RgSchDlSf *dlSf = allocInfo->dlSf; + + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[idx].imcs, tbs); + noLyrs = allocInfo->tbInfo[idx].noLyr; + + if((allocInfo->raType == RG_SCH_CMN_RA_TYPE0)) + { + noRbgs = RGSCH_CEIL((allocInfo->rbsReq + dlSf->lstRbgDfct), cell->rbgSize); + noRbs = (noRbgs * cell->rbgSize) - dlSf->lstRbgDfct; + } + else + { + noRbs = allocInfo->rbsReq; + } + + /* This line will help in case if tbs is zero and reduction in MCS is not possible */ + if (allocInfo->rbsReq == 0 ) + { + RETVOID; + } + origBytesReq = rgTbSzTbl[noLyrs - 1][tbs][rbsReq - 1]/8; + + /* Find out the ITbs & Imcs by identifying first Highest + number of bits compared to the original bytes allocated.*/ + if(tbs > 0) + { + if(((rgTbSzTbl[noLyrs - 1][0][noRbs - 1])/8) < origBytesReq) + { + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgTbSzTbl[noLyrs - 1], tbs); + while(((rgTbSzTbl[noLyrs - 1][tbs][noRbs - 1])/8) > origBytesReq) + { + tbs--; + } + } + else + { + tbs = 0; + } + allocInfo->tbInfo[idx].bytesReq = rgTbSzTbl[noLyrs - 1][tbs][noRbs - 1]/8; + allocInfo->tbInfo[idx].iTbs = tbs; + RG_SCH_CMN_DL_TBS_TO_MCS(tbs,allocInfo->tbInfo[idx].imcs); + } + + RETVOID; +} +/* Added funcion to adjust TBSize*/ +/** + * @brief Function to adjust the tbsize in case of subframe 0 & 5 when + * we were not able to do RB alloc adjustment by adding extra required Rbs + * + * @details + * + * Function : rgSCHCmnNonDlfsPbchTbSizeAdj + * + * Processing Steps: + * + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @param[in] U8 numOvrlapgPbchRb + * @param[in] U8 idx + * @param[in] U8 pbchSsRsSym + * @return void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsPbchTbSizeAdj +( +RgSchDlRbAlloc *allocInfo, +U8 numOvrlapgPbchRb, +U8 pbchSsRsSym, +U8 idx, +U32 bytesReq +) +#else +PRIVATE Void rgSCHCmnNonDlfsPbchTbSizeAdj(allocInfo,numOvrlapgPbchRb,pbchSsRsSym,idx,bytesReq) +RgSchDlRbAlloc *allocInfo; +U8 numOvrlapgPbchRb; +U8 pbchSsRsSym; +U8 idx; +U32 bytesReq; +#endif +{ + U32 reducedTbs = 0; + U8 noLyrs = 0; + U8 tbs = 0; + + noLyrs = allocInfo->tbInfo[idx].noLyr; + + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[idx].imcs, tbs); + + reducedTbs = bytesReq - (((U32)numOvrlapgPbchRb * (U32)pbchSsRsSym * 6)/8); + + /* find out the ITbs & Imcs by identifying first Highest + number of bits compared with reduced bits considering the bits that are + reserved for PBCH/PSS/SSS */ + if(((rgTbSzTbl[noLyrs - 1][0][allocInfo->rbsReq - 1])/8) < reducedTbs) + { + while(((rgTbSzTbl[noLyrs - 1][tbs][allocInfo->rbsReq - 1])/8) > reducedTbs) + { + tbs--; + } + } + else + { + tbs = 0; + } + allocInfo->tbInfo[idx].bytesReq = rgTbSzTbl[noLyrs - 1][tbs][allocInfo->rbsReq - 1]/8; + allocInfo->tbInfo[idx].iTbs = tbs; + RG_SCH_CMN_DL_TBS_TO_MCS(tbs,allocInfo->tbInfo[idx].imcs); + + RETVOID; +} + +/* Added this function to find num of ovrlapping PBCH rb*/ +/** + * @brief Function to find out how many additional rbs are available + * in the entire bw which can be allocated to a UE + * @details + * + * Function : rgSCHCmnFindNumAddtlRbsAvl + * + * Processing Steps: + * - Calculates number of additinal rbs available + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @param[out] U8 addtlRbsAvl + * @return void + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnFindNumAddtlRbsAvl +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo +) +#else +PRIVATE U8 rgSCHCmnFindNumAddtlRbsAvl(cell,dlSf,allocInfo) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +#endif +{ + U8 addtlRbsAvl = 0; + + TRC2(rgSCHCmnFindNumAddtlRbsAvl) + + if (allocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + addtlRbsAvl = (((dlSf->type0End - dlSf->type2End + 1)*\ + cell->rbgSize) - dlSf->lstRbgDfct) - allocInfo->rbsReq; + } + else if (allocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + addtlRbsAvl = (dlSf->bw - dlSf->bwAlloced) - allocInfo->rbsReq; + } + + RETVALUE(addtlRbsAvl); + +} +/* Added this function to find num of ovrlapping PBCH rb*/ +/** + * @brief Function to find out how many of the requested RBs are + * falling in the center 6 RBs of the downlink bandwidth. + * @details + * + * Function : rgSCHCmnFindNumPbchOvrlapRbs + * + * Processing Steps: + * - Calculates number of overlapping rbs + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @param[out] U8* numOvrlapgPbchRb + * @return void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnFindNumPbchOvrlapRbs +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +U8 *numOvrlapgPbchRb +) +#else +PRIVATE Void rgSCHCmnFindNumPbchOvrlapRbs(cell,dlSf,allocInfo,numOvrlapgPbchRb) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +U8 *numOvrlapgPbchRb; +#endif +{ + *numOvrlapgPbchRb = 0; + TRC2(rgSCHCmnFindNumPbchOvrlapRbs) + /*Find if we have already crossed the start boundary for PBCH 6 RBs, + * if yes then lets find the number of RBs which are getting overlapped + * with this allocation.*/ + if(dlSf->bwAlloced <= (cell->pbchRbStart)) + { + /*We have not crossed the start boundary of PBCH RBs. Now we need + * to know that if take this allocation then how much PBCH RBs + * are overlapping with this allocation.*/ + /* Find out the overlapping RBs in the centre 6 RBs */ + if((dlSf->bwAlloced + allocInfo->rbsReq) > cell->pbchRbStart) + { + *numOvrlapgPbchRb = (dlSf->bwAlloced + allocInfo->rbsReq) - (cell->pbchRbStart); + if(*numOvrlapgPbchRb > 6) + *numOvrlapgPbchRb = 6; + } + } + else if ((dlSf->bwAlloced > (cell->pbchRbStart)) && + (dlSf->bwAlloced < (cell->pbchRbEnd))) + { + /*We have already crossed the start boundary of PBCH RBs.We need to + * find that if we take this allocation then how much of the RBs for + * this allocation will overlap with PBCH RBs.*/ + /* Find out the overlapping RBs in the centre 6 RBs */ + if(dlSf->bwAlloced + allocInfo->rbsReq < (cell->pbchRbEnd)) + { + /*If we take this allocation then also we are not crossing the + * end boundary of PBCH 6 RBs.*/ + *numOvrlapgPbchRb = allocInfo->rbsReq; + } + else + { + /*If we take this allocation then we are crossing the + * end boundary of PBCH 6 RBs.*/ + *numOvrlapgPbchRb = (cell->pbchRbEnd) - dlSf->bwAlloced; + } + } + RETVOID; + +} +/** + * @brief Performs RB allocation adjustment if the requested RBs are + * falling in the center 6 RBs of the downlink bandwidth. + * @details + * + * Function : rgSCHCmnNonDlfsPbchRbAllocAdj + * + * Processing Steps: + * - Allocate consecutively available RBs. + * + * @param[in] RgSchCellCb *cell + * @param[in,out] RgSchDlRbAlloc *allocInfo + * @param[in] U8 pbchSsRsSym + * @return void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsPbchRbAllocAdj +( +RgSchCellCb *cell, +RgSchDlRbAlloc *allocInfo, +U8 pbchSsRsSym, +Bool isBcchPcch +) +#else +PRIVATE Void rgSCHCmnNonDlfsPbchRbAllocAdj(cell, allocInfo,pbchSsRsSym) +RgSchCellCb *cell; +RgSchDlRbAlloc *allocInfo; +U8 pbchSsRsSym; +Bool isBcchPcch; +#endif +{ + RgSchDlSf *dlSf = allocInfo->dlSf; + U8 numOvrlapgPbchRb = 0; + U8 numOvrlapgAdtlPbchRb = 0; + U8 totSym; + U8 addtlRbsReq = 0; + U8 moreAddtlRbsReq = 0; + U8 addtlRbsAdd = 0; + U8 moreAddtlRbsAdd = 0; + U8 tbs; + U8 origRbsReq = 0; + U32 bytesReq; + U8 noLyr; + U8 divResult; + + + TRC2(rgSCHCmnNonDlfsPbchRbAllocAdj); + + + origRbsReq = allocInfo->rbsReq; + rgSCHCmnFindNumPbchOvrlapRbs(cell,dlSf,allocInfo,&numOvrlapgPbchRb); + + totSym = (cell->isCpDlExtend) ? RGSCH_TOT_NUM_SYM_EXTCP : RGSCH_TOT_NUM_SYM_NORCP; + + /* Additional RBs are allocated by considering the loss due to + the reserved symbols for CFICH, PBCH, PSS, SSS and cell specific RS */ + + divResult = (numOvrlapgPbchRb * pbchSsRsSym)/totSym; + if((numOvrlapgPbchRb * pbchSsRsSym) % totSym) + { + divResult++; + } + addtlRbsReq = divResult; + + RG_SCH_CMN_UPD_RBS_TO_ADD(cell, dlSf, allocInfo, addtlRbsReq, addtlRbsAdd) + + /*Now RBs requires is original requested RBs + these additional RBs to make + * up for PSS/SSS/BCCH.*/ + allocInfo->rbsReq = allocInfo->rbsReq + addtlRbsAdd; + + /*Check if with these additional RBs we have taken up, these are also falling + * under PBCH RBs range, if yes then we would need to account for + * PSS/BSS/BCCH for these additional RBs too.*/ + if(addtlRbsAdd && ((dlSf->bwAlloced + allocInfo->rbsReq - addtlRbsAdd) < (cell->pbchRbEnd))) + { + if((dlSf->bwAlloced + allocInfo->rbsReq) <= (cell->pbchRbEnd)) + { + /*With additional RBs taken into account, we are not crossing the + * PBCH RB end boundary.Thus here we need to account just for + * overlapping PBCH RBs for these additonal RBs.*/ + divResult = (addtlRbsAdd * pbchSsRsSym)/totSym; + if((addtlRbsAdd * pbchSsRsSym) % totSym) + { + divResult++; + } + + moreAddtlRbsReq = divResult; + + RG_SCH_CMN_UPD_RBS_TO_ADD(cell, dlSf, allocInfo, moreAddtlRbsReq, moreAddtlRbsAdd) + + allocInfo->rbsReq = allocInfo->rbsReq + moreAddtlRbsAdd; + } + else + { + + /*Here we have crossed the PBCH RB end boundary, thus we need to take + * into account the overlapping RBs for additional RBs which will be + * subset of addtlRbs.*/ + numOvrlapgAdtlPbchRb = (cell->pbchRbEnd) - ((dlSf->bwAlloced + allocInfo->rbsReq) - addtlRbsAdd); + + divResult = (numOvrlapgAdtlPbchRb * pbchSsRsSym)/totSym; + if((numOvrlapgAdtlPbchRb * pbchSsRsSym) % totSym) + { + divResult++; + } + + moreAddtlRbsReq = divResult; + + RG_SCH_CMN_UPD_RBS_TO_ADD(cell, dlSf, allocInfo, moreAddtlRbsReq, moreAddtlRbsAdd) + + allocInfo->rbsReq = allocInfo->rbsReq + moreAddtlRbsAdd; + } + } + if (isBcchPcch == TRUE) + { + RETVOID; + } + + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + if(tbs == 6) + { + /* This case might be for Imcs value 6 and NPrb = 1 case - Not + Adjusting either RBs or Imcs or Bytes Allocated */ + allocInfo->rbsReq = allocInfo->rbsReq - addtlRbsAdd - moreAddtlRbsAdd; + } + else if(tbs && ((0 == addtlRbsAdd) && (moreAddtlRbsAdd == 0))) + { + /*In case of a situation where we the entire bandwidth is already occupied + * and we dont have room to add additional Rbs then in order to decrease the + * code rate we reduce the tbsize such that we reduce the present calculated + * tbsize by number of bytes that would be occupied by PBCH/PSS/SSS in overlapping + * rbs and find the nearest tbsize which would be less than this deduced value*/ + + rgSCHCmnFindNumPbchOvrlapRbs(cell,dlSf,allocInfo,&numOvrlapgPbchRb); + + noLyr = allocInfo->tbInfo[0].noLyr; + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgTbSzTbl[noLyr - 1], tbs); + bytesReq = rgTbSzTbl[noLyr - 1][tbs][allocInfo->rbsReq - 1]/8; + + rgSCHCmnNonDlfsPbchTbSizeAdj(allocInfo,numOvrlapgPbchRb,pbchSsRsSym,0,bytesReq); + + if(allocInfo->tbInfo[1].schdlngForTb == TRUE) + { + noLyr = allocInfo->tbInfo[1].noLyr; + bytesReq = rgTbSzTbl[noLyr - 1][tbs][allocInfo->rbsReq - 1]/8; + rgSCHCmnNonDlfsPbchTbSizeAdj(allocInfo,numOvrlapgPbchRb,pbchSsRsSym,1,bytesReq); + } + + } + else if(tbs && ((addtlRbsAdd != addtlRbsReq) || + (addtlRbsAdd && (moreAddtlRbsReq != moreAddtlRbsAdd)))) + { + /*In case of a situation where we were not able to add required number of + * additional RBs then we adjust the Imcs based on original RBs requested. + * Doing this would comensate for the few extra Rbs we have added but inorder + * to comensate for number of RBS we couldnt add we again do the TBSize adjustment*/ + + rgSCHCmnNonDlfsPbchTbImcsAdj(cell, allocInfo, 0 , origRbsReq); + + if(allocInfo->tbInfo[1].schdlngForTb == TRUE) + { + rgSCHCmnNonDlfsPbchTbImcsAdj(cell, allocInfo, 1 , origRbsReq); + } + + rgSCHCmnFindNumPbchOvrlapRbs(cell,dlSf,allocInfo,&numOvrlapgPbchRb); + numOvrlapgPbchRb = numOvrlapgPbchRb - (addtlRbsAdd + moreAddtlRbsAdd); + + rgSCHCmnNonDlfsPbchTbSizeAdj(allocInfo,numOvrlapgPbchRb,pbchSsRsSym,0,allocInfo->tbInfo[0].bytesReq); + + if(allocInfo->tbInfo[1].schdlngForTb == TRUE) + { + rgSCHCmnNonDlfsPbchTbSizeAdj(allocInfo,numOvrlapgPbchRb,pbchSsRsSym,1,allocInfo->tbInfo[1].bytesReq); + } + + } + else + { + /*We hit this code when we were able to add the required additional RBS + * hence we should adjust the IMcs based on orignals RBs requested*/ + + rgSCHCmnNonDlfsPbchTbImcsAdj(cell, allocInfo, 0 , origRbsReq); + + if(allocInfo->tbInfo[1].schdlngForTb == TRUE) + { + rgSCHCmnNonDlfsPbchTbImcsAdj(cell, allocInfo, 1 , origRbsReq); + } + } + + RETVOID; +} /* end of rgSCHCmnNonDlfsPbchRbAllocAdj */ +#endif + +/** + * @brief Performs RB allocation for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsCmnRbAlloc + * + * Processing Steps: + * - Allocate consecutively available RBs for BCCH/PCCH/RAR. + * + * @param[in] RgSchCellCb *cell + * @param[in, out] RgSchDlRbAlloc *allocInfo + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsCmnRbAlloc +( +RgSchCellCb *cell, +RgSchDlRbAlloc *allocInfo +) +#else +PRIVATE S16 rgSCHCmnNonDlfsCmnRbAlloc(cell, allocInfo) +RgSchCellCb *cell; +RgSchDlRbAlloc *allocInfo; +#endif +{ +#ifndef LTE_TDD +#ifdef LTEMAC_SPS +#endif + U8 pbchSsRsSym = 0; + U8 pbchFrame = 0; + U8 tbs = 0; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); +#endif + RgSchDlSf *dlSf = allocInfo->dlSf; +#ifdef LTEMAC_SPS + U8 rbStart = 0; + U8 spsRbsAlloc = 0; + RgSchDlSfAllocInfo *dlSfAlloc = &allocInfo->dlSf->dlSfAllocInfo; +#endif + TRC2(rgSCHCmnNonDlfsCmnRbAlloc); + + allocInfo->tbInfo[0].noLyr = 1; + +#ifdef LTEMAC_SPS + /* Note: Initialize the masks to 0, this might not be needed since alloInfo + * is initialized to 0 at the beginning of allcoation */ + allocInfo->resAllocInfo.raType0Mask = 0; + cmMemset((U8*)allocInfo->resAllocInfo.raType1Mask, 0, + RG_SCH_NUM_RATYPE1_32BIT_MASK * sizeof (U32)); + cmMemset((U8*)allocInfo->resAllocInfo.raType2Mask, 0, + RG_SCH_NUM_RATYPE2_32BIT_MASK * sizeof (U32)); + + if ((dlSf->spsAllocdBw >= cell->spsBwRbgInfo.numRbs) && + (dlSf->bwAlloced == dlSf->bw)) +#else + if(dlSf->bwAlloced == dlSf->bw) +#endif + { + RETVALUE(RFAILED); + } +#ifndef LTE_TDD + if (allocInfo->rbsReq > (dlSf->bw - dlSf->bwAlloced)) + { +#ifdef LTEMAC_SPS + if ((allocInfo->tbInfo[0].imcs < 29) && (dlSf->bwAlloced < dlSf->bw)) +#else + if(allocInfo->tbInfo[0].imcs < 29) +#endif + { + /* set the remaining RBs for the requested UE */ + allocInfo->rbsReq = dlSf->bw - dlSf->bwAlloced; + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + allocInfo->tbInfo[0].bytesReq = rgTbSzTbl[0][tbs][allocInfo->rbsReq - 1]/8; + } + else + { +#ifdef LTEMAC_SPS + /* Attempt RA Type 2 allocation in SPS Bandwidth */ + if (dlSf->spsAllocdBw < cell->spsBwRbgInfo.numRbs) + { + spsRbsAlloc = + rgSCHCmnDlRaType2Alloc(dlSfAlloc, + allocInfo->rbsReq, &cell->spsBwRbgInfo, &rbStart, + &allocInfo->resAllocInfo, FALSE); + /* rbsAlloc assignment moved from line 16671 to here to avoid + * compilation error. Recheck */ + dlSf->spsAllocdBw += spsRbsAlloc; + } + if (!spsRbsAlloc) +#endif /* LTEMAC_SPS */ + { + RETVALUE(RFAILED); + } + } + } +#endif + + /* Update allocation information */ + allocInfo->pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf); + if (allocInfo->pdcch == NULLP) + { + RETVALUE(RFAILED); + } + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_1A]; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + allocInfo->allocInfo.raType2.isLocal = TRUE; +#ifdef LTEMAC_SPS + if (spsRbsAlloc) + { + allocInfo->allocInfo.raType2.rbStart = rbStart; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + allocInfo->rbsAlloc = allocInfo->rbsReq; + } +#endif + +#ifdef LTEMAC_SPS + if (!spsRbsAlloc) + { +#endif +#ifndef LTE_TDD + if(dlSf->sfNum) + { + if(!(dlSf->sfNum == 5)) + { + /* case for subframes 1 to 9 except 5 */ +#ifdef LTEMAC_SPS + allocInfo->allocInfo.raType2.rbStart = rbStart; +#else + /*Fix for ccpu00123918*/ + allocInfo->allocInfo.raType2.rbStart = (U8)dlSf->type2Start; +#endif + } + else + { + pbchFrame = 1; /* case for subframe 5 */ + /* In subframe 5, symbols are reserved for PSS and SSS and CFICH + and Cell Specific Reference Signals */ + pbchSsRsSym = (((cellDl->currCfi) + RGSCH_NUM_PSS_SSS_SYM) * + RGSCH_NUM_SC_IN_RB + cell->numCellRSPerSf); + } + } + else + { + pbchFrame = 1; + /* In subframe 0, symbols are reserved for PSS, SSS, PBCH, CFICH and + and Cell Specific Reference signals */ + pbchSsRsSym = (((cellDl->currCfi) + RGSCH_NUM_PBCH_SYM + + RGSCH_NUM_PSS_SSS_SYM) * RGSCH_NUM_SC_IN_RB + + cell->numCellRSPerSf); + } /* end of outer else */ + + if((pbchFrame) && + (((dlSf->bwAlloced + allocInfo->rbsReq) - cell->pbchRbStart) > 0)&& + (dlSf->bwAlloced < cell->pbchRbEnd)) + { + if(allocInfo->tbInfo[0].imcs < 29) + { + rgSCHCmnNonDlfsPbchRbAllocAdj(cell, allocInfo, pbchSsRsSym, TRUE); + } + } +#endif +#ifdef LTEMAC_SPS + } +#endif + +#ifdef LTEMAC_SPS + if (!spsRbsAlloc) + { +#endif + /*Fix for ccpu00123918*/ + allocInfo->allocInfo.raType2.rbStart = (U8)dlSf->type2Start; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + allocInfo->rbsAlloc = allocInfo->rbsReq; + + /* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD + if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE) + { + rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc(cell, dlSf, \ + allocInfo->allocInfo.raType2.rbStart, \ + allocInfo->allocInfo.raType2.numRb); + } + else +#endif + { + rgSCHCmnNonDlfsUpdTyp2Alloc(cell, dlSf, \ + allocInfo->allocInfo.raType2.rbStart, \ + allocInfo->allocInfo.raType2.numRb); + } + +#ifdef LTEMAC_SPS + } +#endif + /* LTE_ADV_FLAG_REMOVED_END */ + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + + +#ifdef LTEMAC_SPS + if (spsRbsAlloc) + { + U8 idx; + /* Update type 0, 1 and 2 masks */ + dlSfAlloc->raType0Mask |= allocInfo->resAllocInfo.raType0Mask; +#ifdef RGSCH_SPS_UNUSED + for (idx = 0; idx < RG_SCH_NUM_RATYPE1_32BIT_MASK; ++idx) + { + dlSfAlloc->raType1Mask[idx] |= + allocInfo->resAllocInfo.raType1Mask[idx]; + dlSfAlloc->raType1UsedRbs[idx] += + allocInfo->resAllocInfo.raType1UsedRbs[idx]; + } +#endif + for (idx = 0; idx < RG_SCH_NUM_RATYPE2_32BIT_MASK; ++idx) + { + dlSfAlloc->raType2Mask[idx] |= + allocInfo->resAllocInfo.raType2Mask[idx]; + } + } +#endif + + RETVALUE(ROK); +} + + +/** + * @brief Performs RB allocation for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsCmnRbAllocRar + * + * Processing Steps: + * - Allocate consecutively available RBs for BCCH/PCCH/RAR. + * + * @param[in] RgSchCellCb *cell + * @param[in, out] RgSchDlRbAlloc *allocInfo + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsCmnRbAllocRar +( + RgSchCellCb *cell, + RgSchDlRbAlloc *allocInfo + ) +#else +PRIVATE S16 rgSCHCmnNonDlfsCmnRbAlloc(cell, allocInfo) + RgSchCellCb *cell; + RgSchDlRbAlloc *allocInfo; +#endif +{ + RgSchDlSf *dlSf = allocInfo->dlSf; + TRC2(rgSCHCmnNonDlfsCmnRbAllocRar); + + + if(dlSf->bwAlloced == dlSf->bw) + { + RETVALUE(RFAILED); + } + + allocInfo->tbInfo[0].noLyr = 1; +#ifndef RG_5GTF + /* Update allocation information */ + allocInfo->pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf); + if (allocInfo->pdcch == NULLP) + { + RETVALUE(RFAILED); + } + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_1A]; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + allocInfo->allocInfo.raType2.isLocal = TRUE; + + /*Fix for ccpu00123918*/ + allocInfo->allocInfo.raType2.rbStart = (U8)dlSf->type2Start; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + allocInfo->rbsAlloc = allocInfo->rbsReq; + + /* LTE_ADV_FLAG_REMOVED_END */ + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + +#else + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, NULLP, dlSf, 13, TFU_DCI_FORMAT_B1, FALSE); + if (allocInfo->pdcch == NULLP) + { + RETVALUE(RFAILED); + } + RgSchSfBeamInfo *beamInfo = &(dlSf->sfBeamInfo[0]); + if(beamInfo->totVrbgAllocated > MAX_5GTF_VRBG) + { + printf("5GTF_ERROR vrbg allocated > 25\n"); + RETVALUE(RFAILED); + } + + allocInfo->tbInfo[0].cmnGrnt.vrbgStart = beamInfo->vrbgStart; + allocInfo->tbInfo[0].cmnGrnt.numVrbg = allocInfo->vrbgReq; + + /* Update allocation information */ + allocInfo->dciFormat = TFU_DCI_FORMAT_B1; + + allocInfo->tbInfo[0].cmnGrnt.xPDSCHRange = 1; + allocInfo->tbInfo[0].cmnGrnt.rbAssign = rgSCHCmnCalcRiv(MAX_5GTF_VRBG, + allocInfo->tbInfo[0].cmnGrnt.vrbgStart, allocInfo->tbInfo[0].cmnGrnt.numVrbg); + + allocInfo->tbInfo[0].cmnGrnt.rbStrt = (allocInfo->tbInfo[0].cmnGrnt.vrbgStart * MAX_5GTF_VRBG_SIZE); + allocInfo->tbInfo[0].cmnGrnt.numRb = (allocInfo->tbInfo[0].cmnGrnt.numVrbg * MAX_5GTF_VRBG_SIZE); + + beamInfo->vrbgStart += allocInfo->tbInfo[0].cmnGrnt.numVrbg; + beamInfo->totVrbgAllocated += allocInfo->tbInfo[0].cmnGrnt.numVrbg; + allocInfo->tbInfo[0].cmnGrnt.rv = 0; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + +#endif + printf("\n[%s],allocInfo->tbInfo[0].bytesAlloc:%u,vrbgReq:%u\n", + __func__,allocInfo->tbInfo[0].bytesAlloc,allocInfo->vrbgReq); + + RETVALUE(ROK); +} + + +/* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD +/** + * @brief To check if DL BW available for non-DLFS allocation. + * + * @details + * + * Function : rgSCHCmnNonDlfsBwAvlbl + * + * Processing Steps: + * - Determine availability based on RA Type. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchDlRbAlloc *allocInfo + * + * @return Bool + * -# TRUE + * -# FALSE + **/ +#ifdef ANSI +PRIVATE Bool rgSCHCmnNonDlfsSFRBwAvlbl +( +RgSchCellCb *cell, +RgSchSFRPoolInfo **sfrpoolInfo, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +Bool isUeCellEdge +) +#else +PRIVATE Bool rgSCHCmnNonDlfsSFRBwAvlbl(cell, sfrpoolInfo, dlSf, allocInfo, isUeCellEdge) +RgSchCellCb *cell; +RgSchSFRPoolInfo **sfrpoolInfo; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +Bool isUeCellEdge; +#endif +{ + CmLListCp *l; + CmLListCp *l1; + CmLList *n; + CmLList *n1; + RgSchSFRPoolInfo *sfrPool; + RgSchSFRPoolInfo *sfrCEPool; + + U8 tbs; + U8 noLyrs; + RgSchSFRPoolInfo *poolWithMaxAvlblBw = NULLP; + U32 bwAvlbl = 0; + U32 addtnlPRBs = 0; + + if (dlSf->bw <= dlSf->bwAlloced) + { + RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, + "BW is fully allocated for subframe (%d) CRNTI:%d", dlSf->sfNum,allocInfo->rnti); + return FALSE; + } + + if (dlSf->sfrTotalPoolInfo.ccBwFull == TRUE) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "BW is fully allocated for CC Pool CRNTI:%d",allocInfo->rnti); + return FALSE; + } + + if ((dlSf->sfrTotalPoolInfo.ceBwFull == TRUE) && (isUeCellEdge)) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, + "BW is fully allocated for CE Pool CRNTI:%d",allocInfo->rnti); + return FALSE; + } + + /* We first check if the ue scheduled is a cell edge or cell centre and accordingly check the avaialble + memory in their pool. If the cell centre UE doesnt have Bw available in its pool, then it will check + Bw availability in cell edge pool but the other way around is NOT possible. */ + if(isUeCellEdge) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + } + else + { + l = &dlSf->sfrTotalPoolInfo.ccPool; + } + + n = cmLListFirst(l); + + while(n) + { + if (allocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + sfrPool = (RgSchSFRPoolInfo*)(n->node); + + /* MS_FIX for ccpu00123919 : Number of RBs in case of RETX should be same as that of initial transmission. */ + if(allocInfo->tbInfo[0].tbCb->txCntr) + { + /* If RB assignment is being done for RETX. Then if reqRbs are a multiple of rbgSize then ignore lstRbgDfct. If reqRbs is + * not a multiple of rbgSize then check if lsgRbgDfct exists */ + if (allocInfo->rbsReq % cell->rbgSize == 0) + { + if ((sfrPool->type2End == dlSf->type2End) && dlSf->lstRbgDfct) + { + /* In this scenario we are wasting the last RBG for this dlSf */ + sfrPool->type0End--; + sfrPool->bwAlloced += (cell->rbgSize - dlSf->lstRbgDfct); + + dlSf->lstRbgDfct = 0; + + /*ABHINAV To check if these variables need to be taken care of*/ + dlSf->type0End--; + dlSf->bwAlloced += (cell->rbgSize - dlSf->lstRbgDfct); + } + } + else + { + if (dlSf->lstRbgDfct) + { + /* Check if type0 allocation can cater to this RETX requirement */ + if ((allocInfo->rbsReq % cell->rbgSize) != (cell->rbgSize - dlSf->lstRbgDfct)) + { + RETVALUE(FALSE); + } + else + { + if (sfrPool->type2End != dlSf->type2End) /*Search again for some pool which has the END RBG of the BandWidth*/ + { + continue; + } + } + } + else + { + /* cannot allocate same number of required RBs */ + RETVALUE(FALSE); + } + } + } + + /*rg002.301 ccpu00120391 MOD condition is modified approprialtely to find if rbsReq is less than available RBS*/ + if(allocInfo->rbsReq <= (((sfrPool->type0End - sfrPool->type2End + 1)*\ + cell->rbgSize) - dlSf->lstRbgDfct)) + { + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + else + { + if (sfrPool->bw <= sfrPool->bwAlloced + cell->rbgSize) + { + n = cmLListNext(l); + /* If the ue is cell centre then it will simply check the memory available in next pool. + But if there are no more memory pools available, then cell centre Ue will try to look for memory in cell edge pool */ + + if((!isUeCellEdge) && (!n->node)) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + n = cmLListFirst(l); + } + + continue; + } + + /* MS_FIX: Number of RBs in case of RETX should be same as that of initial transmission */ + if(allocInfo->tbInfo[0].tbCb->txCntr == 0) + { + /*rg002.301 ccpu00120391 MOD setting the remaining RBs for the requested UE*/ + allocInfo->rbsReq = (((sfrPool->type0End - sfrPool->type2End + 1)*\ + cell->rbgSize) - dlSf->lstRbgDfct); + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + noLyrs = allocInfo->tbInfo[0].noLyr; + allocInfo->tbInfo[0].bytesReq = rgTbSzTbl[noLyrs-1][tbs][allocInfo->rbsReq - 1]/8; + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + else + { + n = cmLListNext(l); + + /* If the ue is cell centre then it will simply check the memory available in next pool. + But if there are no more memory pools available, then cell centre Ue will try to look for memory in cell edge pool */ + if((!isUeCellEdge) && (!n->node)) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + n = cmLListFirst(l); + } + + continue; + } + + // RETVALUE(FALSE); + } + } + else if (allocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + sfrPool = (RgSchSFRPoolInfo*)(n->node); + /* This is a Case where a UE was CC and had more RBs allocated than present in CE pool. + In case this UE whn become CE with retx going on, then BW is not sufficient for Retx */ + if ((isUeCellEdge) && + (allocInfo->tbInfo[0].tbCb->txCntr != 0)) + { + if(allocInfo->rbsReq > (sfrPool->bw - sfrPool->bwAlloced)) + { + /* Adjust CE BW such that Retx alloc is successful */ + /* Check if merging CE with adjacent CC pool will be sufficient to process Retx */ + + /* If no Type 0 allocations are made from this pool */ + if (sfrPool->type0End == (((sfrPool->poolendRB + 1) / cell->rbgSize) - 1)) + { + if (sfrPool->adjCCPool && + (sfrPool->adjCCPool->type2Start == sfrPool->poolendRB + 1) && + (allocInfo->rbsReq <= ((sfrPool->bw - sfrPool->bwAlloced) + + ((sfrPool->adjCCPool->bw - sfrPool->adjCCPool->bwAlloced))))) + { + addtnlPRBs = allocInfo->rbsReq - (sfrPool->bw - sfrPool->bwAlloced); + + /* Adjusting CE Pool Info */ + sfrPool->bw += addtnlPRBs; + sfrPool->type0End = ((sfrPool->poolendRB + addtnlPRBs + 1) / + cell->rbgSize) - 1; + + /* Adjusting CC Pool Info */ + sfrPool->adjCCPool->type2Start += addtnlPRBs; + sfrPool->adjCCPool->type2End = RGSCH_CEIL(sfrPool->adjCCPool->type2Start, + cell->rbgSize); + sfrPool->adjCCPool->bw -= addtnlPRBs; + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + } + } + } + + /* Check if CC pool is one of the following: + * 1. |CE| + |CC "CCPool2Exists" = TRUE| + * 2. |CC "CCPool2Exists" = FALSE| + |CE| + |CC "CCPool2Exists" = TRUE| + */ + if(TRUE == sfrPool->CCPool2Exists) + { + l1 = &dlSf->sfrTotalPoolInfo.cePool; + n1 = cmLListFirst(l1); + sfrCEPool = (RgSchSFRPoolInfo*)(n1->node); + if(allocInfo->rbsReq <= (sfrCEPool->bw - sfrCEPool->bwAlloced)) + { + *sfrpoolInfo = sfrCEPool; + RETVALUE(TRUE); + } + else if(allocInfo->rbsReq <= (sfrPool->bw - sfrPool->bwAlloced)) + { + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + /* Check if CE and CC boundary has unallocated prbs */ + else if ((sfrPool->poolstartRB == sfrPool->type2Start) && + (sfrCEPool->type0End == ((sfrCEPool->poolendRB + 1) / cell->rbgSize) - 1)) + { + if(allocInfo->rbsReq <= (sfrCEPool->bw - sfrCEPool->bwAlloced) + + (sfrPool->bw - sfrPool->bwAlloced)) + { + /* Checking if BW can be allocated partly from CE pool and partly + * from CC pool + */ + addtnlPRBs = allocInfo->rbsReq - (sfrPool->bw - sfrPool->bwAlloced); + /* Updating CE and CC type2 parametrs based on the RBs allocated + * from these pools*/ + sfrPool->type2Start -= addtnlPRBs; + sfrPool->type2End = RGSCH_CEIL(sfrPool->type2Start, cell->rbgSize); + sfrPool->bw += addtnlPRBs; + if (addtnlPRBs == (sfrCEPool->bw - sfrCEPool->bwAlloced)) + { + sfrCEPool->bwAlloced = sfrCEPool->bw; + dlSf->sfrTotalPoolInfo.ceBwFull = TRUE; + } + else + { + sfrCEPool->bw -= addtnlPRBs; + sfrCEPool->type0End = ((sfrCEPool->poolendRB + 1 - addtnlPRBs) / cell->rbgSize) - 1; + } + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + else if ( bwAvlbl < + ((sfrCEPool->bw - sfrCEPool->bwAlloced) + + (sfrPool->bw - sfrPool->bwAlloced))) + { + /* All the Prbs from CE BW shall be allocated */ + if(allocInfo->tbInfo[0].tbCb->txCntr == 0) + { + sfrPool->type2Start = sfrCEPool->type2Start; + sfrPool->bw += sfrCEPool->bw - sfrCEPool->bwAlloced; + sfrCEPool->type2Start = sfrCEPool->poolendRB + 1; + sfrCEPool->bwAlloced = sfrCEPool->bw; + dlSf->sfrTotalPoolInfo.ceBwFull = TRUE; + + /* set the remaining RBs for the requested UE */ + allocInfo->rbsReq = (sfrPool->bw - sfrPool->bwAlloced); + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + noLyrs = allocInfo->tbInfo[0].noLyr; + allocInfo->tbInfo[0].bytesReq = + rgTbSzTbl[noLyrs-1][tbs][allocInfo->rbsReq - 1]/8; + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + else + { + RETVALUE(FALSE); + } + } + } + } + + /* Checking if no. of RBs required can be allocated from + * SFR pool. + * 1. If available return the SFR pool. + * 2. Else update the RBs required parameter based on the + * BW available in the pool + * 3. Return FALSE if no B/W is available. + */ + if (allocInfo->rbsReq <= (sfrPool->bw - sfrPool->bwAlloced)) + { + *sfrpoolInfo = sfrPool; + RETVALUE(TRUE); + } + else + { + if(allocInfo->tbInfo[0].tbCb->txCntr == 0) + { + if (bwAvlbl < sfrPool->bw - sfrPool->bwAlloced) + { + if (isUeCellEdge) + { + dlSf->sfrTotalPoolInfo.ceBwFull = TRUE; + } + bwAvlbl = sfrPool->bw - sfrPool->bwAlloced; + poolWithMaxAvlblBw = sfrPool; + } + n = cmLListNext(l); + + if ((isUeCellEdge == FALSE) && (n == NULLP)) + { + if(l != &dlSf->sfrTotalPoolInfo.cePool) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + n = cmLListFirst(l); + } + } + + if (n == NULLP) + { + if (bwAvlbl == 0) + { + if (isUeCellEdge) + { + dlSf->sfrTotalPoolInfo.ceBwFull = TRUE; + } + else + { + dlSf->sfrTotalPoolInfo.ccBwFull = TRUE; + } + RETVALUE(FALSE); + } + else + { + /* set the remaining RBs for the requested UE */ + allocInfo->rbsReq = poolWithMaxAvlblBw->bw - + poolWithMaxAvlblBw->bwAlloced; + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + noLyrs = allocInfo->tbInfo[0].noLyr; + allocInfo->tbInfo[0].bytesReq = + rgTbSzTbl[noLyrs-1][tbs][allocInfo->rbsReq - 1]/8; + *sfrpoolInfo = poolWithMaxAvlblBw; + RETVALUE(TRUE); + } + } + } + else + { + n = cmLListNext(l); + + if ((isUeCellEdge == FALSE) && (n == NULLP)) + { + if(l != &dlSf->sfrTotalPoolInfo.cePool) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + n = cmLListFirst(l); + } + } + + if (n == NULLP) + { + RETVALUE(FALSE); + } + } + + } + } + } + RETVALUE(FALSE); +} +#endif /* end of ifndef LTE_TDD*/ +/* LTE_ADV_FLAG_REMOVED_END */ + +/** + * @brief To check if DL BW available for non-DLFS allocation. + * + * @details + * + * Function : rgSCHCmnNonDlfsUeRbAlloc + * + * Processing Steps: + * - Determine availability based on RA Type. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchDlRbAlloc *allocInfo + * + * @return Bool + * -# TRUE + * -# FALSE + **/ +#ifdef ANSI +PRIVATE Bool rgSCHCmnNonDlfsBwAvlbl +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo +) +#else +PRIVATE Bool rgSCHCmnNonDlfsBwAvlbl(cell, dlSf, allocInfo) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +#endif +{ + U8 tbs; + U8 noLyrs; + U8 ignoredDfctRbg = FALSE; + + TRC2(rgSCHCmnNonDlfsBwAvlbl); + if (dlSf->bw <= dlSf->bwAlloced) + { + RLOG_ARG3(L_DEBUG,DBG_CELLID,cell->cellId, "(%d:%d)FAILED CRNTI:%d", + dlSf->bw, dlSf->bwAlloced,allocInfo->rnti); + RETVALUE(FALSE); + } + if (allocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + /* Fix for ccpu00123919 : Number of RBs in case of RETX should be same as + * that of initial transmission. */ + if(allocInfo->tbInfo[0].tbCb->txCntr) + { + /* If RB assignment is being done for RETX. Then if reqRbs are + * a multiple of rbgSize then ignore lstRbgDfct. If reqRbs is + * not a multiple of rbgSize then check if lsgRbgDfct exists */ + if (allocInfo->rbsReq % cell->rbgSize == 0) + { + if (dlSf->lstRbgDfct) + { + /* In this scenario we are wasting the last RBG for this dlSf */ + + dlSf->type0End--; + dlSf->bwAlloced += (cell->rbgSize - dlSf->lstRbgDfct); + /* Fix: MUE_PERTTI_DL */ + dlSf->lstRbgDfct = 0; + ignoredDfctRbg = TRUE; + + } + } + else + { + if (dlSf->lstRbgDfct) + { + /* Check if type0 allocation can cater to this RETX requirement */ + if ((allocInfo->rbsReq % cell->rbgSize) != (cell->rbgSize - dlSf->lstRbgDfct)) + { + RETVALUE(FALSE); + } + } + else + { + /* cannot allocate same number of required RBs */ + RETVALUE(FALSE); + } + } + } + + /* Condition is modified approprialtely to find + * if rbsReq is less than available RBS*/ + if(allocInfo->rbsReq <= (((dlSf->type0End - dlSf->type2End + 1)*\ + cell->rbgSize) - dlSf->lstRbgDfct)) + { + RETVALUE(TRUE); + } + /* ccpu00132358:MOD- Removing "ifndef LTE_TDD" for unblocking the RB + * allocation in TDD when requested RBs are more than available RBs*/ + else + { + /* MS_WORKAROUND for ccpu00122022 */ + if (dlSf->bw < dlSf->bwAlloced + cell->rbgSize) + { + /* ccpu00132358- Re-assigning the values which were updated above + * if it is RETX and Last RBG available*/ + if(ignoredDfctRbg == TRUE) + { + dlSf->type0End++; + dlSf->bwAlloced -= (cell->rbgSize - dlSf->lstRbgDfct); + dlSf->lstRbgDfct = 1; + } + + + RETVALUE(FALSE); + } + /* Fix: Number of RBs in case of RETX should be same as + * that of initial transmission. */ + if(allocInfo->tbInfo[0].tbCb->txCntr == 0 +#ifdef LTE_ADV + && (FALSE == rgSCHLaaIsLaaTB(allocInfo)) +#endif + ) + { + /* Setting the remaining RBs for the requested UE*/ + allocInfo->rbsReq = (((dlSf->type0End - dlSf->type2End + 1)*\ + cell->rbgSize) - dlSf->lstRbgDfct); + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + noLyrs = allocInfo->tbInfo[0].noLyr; + allocInfo->tbInfo[0].bytesReq = rgTbSzTbl[noLyrs-1][tbs][allocInfo->rbsReq - 1]/8; + /* DwPts Scheduling Changes Start */ +#if LTE_TDD + if (dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + allocInfo->tbInfo[0].bytesReq = + rgTbSzTbl[noLyrs-1][tbs][RGSCH_MAX(allocInfo->rbsReq*3/4,1) - 1]/8; + } +#endif + /* DwPts Scheduling Changes End */ + } + else + { + /* ccpu00132358- Re-assigning the values which were updated above + * if it is RETX and Last RBG available*/ + if(ignoredDfctRbg == TRUE) + { + dlSf->type0End++; + dlSf->bwAlloced -= (cell->rbgSize - dlSf->lstRbgDfct); + dlSf->lstRbgDfct = 1; + } + + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "FAILED for CRNTI:%d", + allocInfo->rnti); + printf ("RB Alloc failed for LAA TB type 0\n"); + RETVALUE(FALSE); + } + RETVALUE(TRUE); + } + } + else if (allocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + if (allocInfo->rbsReq <= (dlSf->bw - dlSf->bwAlloced)) + { + RETVALUE(TRUE); + } + /* ccpu00132358:MOD- Removing "ifndef LTE_TDD" for unblocking the RB + * allocation in TDD when requested RBs are more than available RBs*/ + else + { + /* Fix: Number of RBs in case of RETX should be same as + * that of initial transmission. */ + if((allocInfo->tbInfo[0].tbCb->txCntr == 0) +#ifdef LTE_ADV + && (FALSE == rgSCHLaaIsLaaTB(allocInfo)) +#endif + ) + { + /* set the remaining RBs for the requested UE */ + allocInfo->rbsReq = dlSf->bw - dlSf->bwAlloced; + RG_SCH_CMN_DL_MCS_TO_TBS(allocInfo->tbInfo[0].imcs, tbs); + noLyrs = allocInfo->tbInfo[0].noLyr; + allocInfo->tbInfo[0].bytesReq = rgTbSzTbl[noLyrs-1][tbs][allocInfo->rbsReq - 1]/8; + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if (dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + allocInfo->tbInfo[0].bytesReq = + rgTbSzTbl[noLyrs-1][tbs][RGSCH_MAX(allocInfo->rbsReq*3/4,1) - 1]/8; + } +#endif + /* DwPts Scheduling Changes End */ + } + else + { + printf ("RB Alloc failed for LAA TB type 2\n"); + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"FAILED for CRNTI:%d",allocInfo->rnti); + RETVALUE(FALSE); + } + /* Fix: Number of RBs in case of RETX should be same as + * that of initial transmission. */ + RETVALUE(TRUE); + } + } + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"FAILED for CRNTI:%d",allocInfo->rnti); + RETVALUE(FALSE); +} +/* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD +/** + * @brief To update non-DLFS alloc'n parameters after TYPE2 Allocation. + * + * @details + * + * Function : rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc + * + * Processing Steps: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] U8 rbStrt + * @param[in] U8 numRb + * + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +) +#else +PUBLIC Void rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc(cell, dlSf, rbStrt, numRb) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +U8 rbStrt; +U8 numRb; +#endif +{ + CmLListCp *l; + CmLList *n; + RgSchSFRPoolInfo *sfrPool; + TRC2(rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc); + + l = &dlSf->sfrTotalPoolInfo.ccPool; + + dlSf->type2End = RGSCH_CEIL((rbStrt+numRb), cell->rbgSize); + dlSf->bwAlloced += numRb; + dlSf->type2Start += numRb; + n = cmLListFirst(l); + + while(n->node) + { + sfrPool = (RgSchSFRPoolInfo*)(n->node); + n = cmLListNext(l); + + /* If the pool contains some RBs allocated in this allocation, e.g: Pool is [30.50]. Pool->type2Start is 40 , dlSf->type2Start is 45. then update the variables in pool */ + if((sfrPool->poolendRB >= dlSf->type2Start) && (sfrPool->type2Start < dlSf->type2Start)) + { + sfrPool->type2End = dlSf->type2End; + sfrPool->bwAlloced = dlSf->type2Start - sfrPool->poolstartRB; + sfrPool->type2Start = dlSf->type2Start; + } + else + { + /* If the pool contains all RBs allocated in this allocation*/ + if(dlSf->type2Start > sfrPool->poolendRB) + { + sfrPool->type2End = sfrPool->type0End + 1; + sfrPool->bwAlloced = sfrPool->bw; + sfrPool->type2Start = sfrPool->poolendRB + 1; + } + } + if (!n) + { + if (l != &dlSf->sfrTotalPoolInfo.cePool) + { + l = &dlSf->sfrTotalPoolInfo.cePool; + n = cmLListFirst(l); + } + else + RETVOID; + } + } + RETVOID; +} + +/** + * @brief To update non-DLFS alloc'n parameters after TYPE2 Allocation. + * + * @details + * + * Function : rgSCHCmnNonDlfsUpdDSFRTyp2Alloc + * + * Processing Steps: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] U8 rbStrt + * @param[in] U8 numRb + * + * @return Void + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsUpdDSFRTyp2Alloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +) +#else +PRIVATE S16 rgSCHCmnNonDlfsUpdDSFRTyp2Alloc(cell, ue, dlSf, rbStrt, numRb) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlSf *dlSf; +U8 rbStrt; +U8 numRb; +#endif +{ + CmLListCp *l; + CmLList *n; + RgSchSFRPoolInfo *sfrCCPool1 = NULL; + RgSchSFRPoolInfo *sfrCCPool2 = NULL; + S16 ret = RFAILED; + + TRC2(rgSCHCmnNonDlfsUpdDSFRTyp2Alloc); + /* Move the type2End pivot forward */ + + + l = &dlSf->sfrTotalPoolInfo.ccPool; + n = cmLListFirst(l); + while(n) + { + sfrCCPool1 = (RgSchSFRPoolInfo*)(n->node); + /* KWork fix */ + if (sfrCCPool1 == NULLP) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnNonDlfsUpdDSFRTyp2Alloc():" + "sfrCCPool1 is NULL for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + n = cmLListNext(l); + if(n) + { + sfrCCPool2 = (RgSchSFRPoolInfo*)(n->node); + n = cmLListNext(l); + } + if((sfrCCPool1) && (sfrCCPool2)) + { + /* Based on RNTP info, the CC user is assigned high power per subframe basis */ + if(((dlSf->type2Start >= sfrCCPool1->pwrHiCCRange.startRb) && + (dlSf->type2Start + numRb < sfrCCPool1->pwrHiCCRange.endRb)) || + ((dlSf->type2Start >= sfrCCPool2->pwrHiCCRange.startRb) && + (dlSf->type2Start + numRb < sfrCCPool2->pwrHiCCRange.endRb))) + { + ue->lteAdvUeCb.isCCUePHigh = TRUE; + + /* Calling rgSCHCmnBuildRntpInfo function to update RNTP BitMap */ + ret = rgSCHCmnBuildRntpInfo(cell, dlSf->rntpInfo.val, dlSf->type2Start, numRb, dlSf->bw); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnNonDlfsUpdDSFRTyp2Alloc():" + "rgSCHCmnBuildRntpInfo() function returned RFAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + } + else + { + if((dlSf->type2Start >= sfrCCPool1->pwrHiCCRange.startRb) && + (dlSf->type2Start + numRb < sfrCCPool1->pwrHiCCRange.endRb)) + { + ue->lteAdvUeCb.isCCUePHigh = TRUE; + + /* Calling rgSCHCmnBuildRntpInfo function to update RNTP BitMap */ + ret = rgSCHCmnBuildRntpInfo(cell, dlSf->rntpInfo.val, dlSf->type2Start, numRb, dlSf->bw); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnNonDlfsUpdDSFRTyp2Alloc():" + "rgSCHCmnBuildRntpInfo() function returned RFAILED CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + } + } + dlSf->type2End = RGSCH_CEIL((rbStrt+numRb), cell->rbgSize); +#ifndef LTEMAC_SPS + dlSf->bwAlloced += numRb; + /*MS_FIX for ccpu00123918*/ + dlSf->type2Start += numRb; +#endif + RETVALUE(ROK); +} +#endif /* end of ifndef LTE_TDD*/ +/* LTE_ADV_FLAG_REMOVED_END */ +/** + * @brief To update non-DLFS alloc'n parameters after TYPE2 Allocation. + * + * @details + * + * Function : rgSCHCmnNonDlfsUpdTyp2Alloc + * + * Processing Steps: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] U8 rbStrt + * @param[in] U8 numRb + * + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsUpdTyp2Alloc +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +U8 rbStrt, +U8 numRb +) +#else +PRIVATE Void rgSCHCmnNonDlfsUpdTyp2Alloc(cell, dlSf, rbStrt, numRb) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +U8 rbStrt; +U8 numRb; +#endif +{ + TRC2(rgSCHCmnNonDlfsUpdTyp2Alloc); + /* Move the type2End pivot forward */ + dlSf->type2End = RGSCH_CEIL((rbStrt+numRb), cell->rbgSize); +//#ifndef LTEMAC_SPS + dlSf->bwAlloced += numRb; + /*Fix for ccpu00123918*/ + dlSf->type2Start += numRb; +//#endif + RETVOID; +} + +/** + * @brief To do DL allocation using TYPE0 RA. + * + * @details + * + * Function : rgSCHCmnNonDlfsType0Alloc + * + * Processing Steps: + * - Perform TYPE0 allocation using the RBGs between + * type0End and type2End. + * - Build the allocation mask as per RBG positioning. + * - Update the allocation parameters. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchDlRbAlloc *allocInfo + * + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsType0Alloc +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchDlRbAlloc *allocInfo, +RgSchUeCb *ue +) +#else +PRIVATE Void rgSCHCmnNonDlfsType0Alloc(cell, dlSf, allocInfo, dlUe) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchDlRbAlloc *allocInfo; +RgSchUeCb *ue; +#endif +{ + U32 dlAllocMsk = 0; + U8 rbgFiller = dlSf->lstRbgDfct; + U8 noRbgs = RGSCH_CEIL((allocInfo->rbsReq + rbgFiller), cell->rbgSize); + //U8 noRbgs = (allocInfo->rbsReq + rbgFiller)/ cell->rbgSize; + U8 noRbs; + U8 noLyr; + U8 iTbs; + U32 tb1BytesAlloc = 0; + U32 tb2BytesAlloc = 0; + RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnNonDlfsType0Alloc); + //if(noRbgs == 0) noRbgs = 1; /* Not required as ceilling is used above*/ + + /* Fix for ccpu00123919*/ + noRbs = (noRbgs * cell->rbgSize) - rbgFiller; + if (dlSf->bwAlloced + noRbs > dlSf->bw) + { + if (--noRbgs == 0) + { + RETVOID; + } + noRbs = (noRbgs * cell->rbgSize) - rbgFiller; + } + + /* Fix for ccpu00138701: Ceilling is using to derive num of RBGs, Therefore, + * after this operation,checking Max TB size and Max RBs are not crossed + * if it is crossed then decrement num of RBGs. */ + //if((noRbs + rbgFiller) % cell->rbgSize) + if((noRbs > allocInfo->rbsReq) && + (allocInfo->rbsReq + rbgFiller) % cell->rbgSize) + {/* considering ue category limitation + * due to ceiling */ + +#ifdef LTE_ADV + if (rgSCHLaaIsLaaTB(allocInfo)== FALSE) +#endif + { + if ((allocInfo->tbInfo[0].schdlngForTb) && (!allocInfo->tbInfo[0].tbCb->txCntr)) + { + iTbs = allocInfo->tbInfo[0].iTbs; + noLyr = allocInfo->tbInfo[0].noLyr; + tb1BytesAlloc = rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8; + } + + if ((allocInfo->tbInfo[1].schdlngForTb) && (!allocInfo->tbInfo[1].tbCb->txCntr)) + { + iTbs = allocInfo->tbInfo[1].iTbs; + noLyr = allocInfo->tbInfo[1].noLyr; + tb2BytesAlloc = rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8; + } + } + + /* Only Check for New Tx No need for Retx */ + if (tb1BytesAlloc || tb2BytesAlloc) + { + if (( ue->dl.aggTbBits >= dlUe->maxTbBits) || + (tb1BytesAlloc >= dlUe->maxTbSz/8) || + (tb2BytesAlloc >= dlUe->maxTbSz/8) || + (noRbs >= dlUe->maxRb)) + { + if (--noRbgs == 0) + { + RETVOID; + } + noRbs = (noRbgs * cell->rbgSize) - rbgFiller; + } + } + } + /* type0End would have been initially (during subfrm Init) at the bit position + * (cell->noOfRbgs - 1), 0 being the most significant. + * Getting DlAllocMsk for noRbgs and at the appropriate position */ + dlAllocMsk |= (((1 << noRbgs) - 1) << (31 - dlSf->type0End)); + /* Move backwards the type0End pivot */ + dlSf->type0End -= noRbgs; + /*Fix for ccpu00123919*/ + /*noRbs = (noRbgs * cell->rbgSize) - rbgFiller;*/ + /* Update the bwAlloced field accordingly */ +//#ifndef LTEMAC_SPS /* ccpu00129474*/ + dlSf->bwAlloced += noRbs; +//#endif + /* Update Type0 Alloc Info */ + allocInfo->allocInfo.raType0.numDlAlloc = noRbgs; + allocInfo->allocInfo.raType0.dlAllocBitMask |= dlAllocMsk; + allocInfo->rbsAlloc = noRbs; + + /* Update Tb info for each scheduled TB */ + iTbs = allocInfo->tbInfo[0].iTbs; + noLyr = allocInfo->tbInfo[0].noLyr; + /* Fix for ccpu00123919: For a RETX TB the iTbs is irrelevant. + * RETX TB Size is same as Init TX TB Size */ + if (allocInfo->tbInfo[0].tbCb->txCntr) + { + allocInfo->tbInfo[0].bytesAlloc = + allocInfo->tbInfo[0].bytesReq; + } + else + { + allocInfo->tbInfo[0].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8; + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if (dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + allocInfo->tbInfo[0].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][RGSCH_MAX(noRbs*3/4,1) - 1]/8; + } +#endif + /* DwPts Scheduling Changes End */ + } + + if (allocInfo->tbInfo[1].schdlngForTb) + { + iTbs = allocInfo->tbInfo[1].iTbs; + noLyr = allocInfo->tbInfo[1].noLyr; + /* Fix for ccpu00123919: For a RETX TB the iTbs is irrelevant + * RETX TB Size is same as Init TX TB Size */ + if (allocInfo->tbInfo[1].tbCb->txCntr) + { + allocInfo->tbInfo[1].bytesAlloc = + allocInfo->tbInfo[1].bytesReq; + } + else + { + allocInfo->tbInfo[1].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8;; + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if (dlSf->sfType == RG_SCH_SPL_SF_DATA) + { + allocInfo->tbInfo[1].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][RGSCH_MAX(noRbs*3/4,1) - 1]/8; + } +#endif + /* DwPts Scheduling Changes End */ + } + } + + /* The last RBG which can be smaller than the RBG size is consedered + * only for the first time allocation of TYPE0 UE */ + dlSf->lstRbgDfct = 0; + RETVOID; +} +#ifndef LTE_TDD + +/** + * @brief To prepare RNTP value from the PRB allocation (P-High -> 1 and P-Low -> 0) + * + * @details + * + * Function : rgSCHCmnBuildRntpInfo + * + * Processing Steps: + * + * @param[in] U8 *rntpPtr + * @param[in] U8 startRb + * @param[in] U8 numRb + * + * @return Void + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnBuildRntpInfo +( +RgSchCellCb *cell, +U8 *rntpPtr, +U8 startRb, +U8 nmbRb, +U16 bw +) +#else +PRIVATE S16 rgSCHCmnBuildRntpInfo(cell, rntpPtr, startRb, nmbRb, bw) +RgSchCellCb *cell; +U8 *rntpPtr; +U8 startRb; +U8 nmbRb; +U16 bw; +#endif +{ + U16 rbPtrStartIdx; /* Start Index of Octete Buffer to be filled */ + U16 rbPtrEndIdx; /* End Index of Octete Buffer to be filled */ + U16 rbBitLoc; /* Bit Location to be set as 1 in the current Byte */ + U16 nmbRbPerByte; /* PRB's to be set in the current Byte (in case of multiple Bytes) */ + + TRC2(rgSCHCmnBuildRntpInfo); + + rbPtrStartIdx = (startRb)/8; + rbPtrEndIdx = (startRb + nmbRb)/8; + + if (rntpPtr == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "rgSCHCmnBuildRntpInfo():" + "rntpPtr can't be NULLP (Memory Allocation Failed)"); + RETVALUE(RFAILED); + } + + while(rbPtrStartIdx <= rbPtrEndIdx) + { + rbBitLoc = (startRb)%8; + + /* case 1: startRb and endRb lies in same Byte */ + if (rbPtrStartIdx == rbPtrEndIdx) + { + rntpPtr[rbPtrStartIdx] = rntpPtr[rbPtrStartIdx] + | (((1<type2End = RGSCH_CEIL((rbStrt+numRb), cell->rbgSize); + sfrPool->type2End = RGSCH_CEIL((rbStrt+numRb), cell->rbgSize); + +#ifndef LTEMAC_SPS + dlSf->type2Start += numRb; + dlSf->bwAlloced += numRb; + + if(cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE) + { + /* Based on RNTP info, the CC user is assigned high power per subframe basis */ + if(FALSE == ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge) + { + if((sfrPool->type2Start >= sfrPool->pwrHiCCRange.startRb) && + (sfrPool->type2Start + numRb < sfrPool->pwrHiCCRange.endRb)) + { + ue->lteAdvUeCb.isCCUePHigh = TRUE; + + /* Calling rgSCHCmnBuildRntpInfo function to update RNTP BitMap */ + ret = rgSCHCmnBuildRntpInfo(cell, dlSf->rntpInfo.val, sfrPool->type2Start, numRb, dlSf->bw); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHCmnNonDlfsUpdSFRPoolTyp2Alloc():" + "rgSCHCmnBuildRntpInfo() function returned RFAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + } + else + { + /* Calling rgSCHCmnBuildRntpInfo function to update RNTP BitMap */ + ret = rgSCHCmnBuildRntpInfo(cell, dlSf->rntpInfo.val, sfrPool->type2Start, numRb, dlSf->bw); + if (ret != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnNonDlfsUpdSFRPoolTyp2Alloc():" + "rgSCHCmnBuildRntpInfo() function returned RFAILED for CRNTI:%d",ue->ueId); + RETVALUE(RFAILED); + } + } + } + sfrPool->type2Start += numRb; + sfrPool->bwAlloced += numRb; +#endif + + RETVALUE(ROK); +} + +/** + * @brief To do DL allocation using TYPE0 RA. + * + * @details + * + * Function : rgSCHCmnNonDlfsSFRPoolType0Alloc + * + * Processing Steps: + * - Perform TYPE0 allocation using the RBGs between type0End and type2End. + * - Build the allocation mask as per RBG positioning. + * - Update the allocation parameters. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *dlSf + * @param[in] RgSchDlRbAlloc *allocInfo + * + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsSFRPoolType0Alloc +( +RgSchCellCb *cell, +RgSchDlSf *dlSf, +RgSchSFRPoolInfo *poolInfo, +RgSchDlRbAlloc *allocInfo +) +#else +PRIVATE Void rgSCHCmnNonDlfsSFRPoolType0Alloc(cell, dlSf, poolInfo, allocInfo) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +RgSchSFRPoolInfo *poolInfo; +RgSchDlRbAlloc *allocInfo; +#endif +{ + U32 dlAllocMsk = 0; + U8 rbgFiller = 0; + U8 noRbgs = 0; + U8 noRbs; + U8 noLyr; + U8 iTbs; + + TRC2(rgSCHCmnNonDlfsSFRPoolType0Alloc); + + if (poolInfo->poolstartRB + poolInfo->bw == dlSf->bw) + { + if (poolInfo->type0End == dlSf->bw/4) + { + rbgFiller = dlSf->lstRbgDfct; + /* The last RBG which can be smaller than the RBG size is consedered + * only for the first time allocation of TYPE0 UE */ + dlSf->lstRbgDfct = 0; + } + } + + noRbgs = RGSCH_CEIL((allocInfo->rbsReq + rbgFiller), cell->rbgSize); + + /* Abhinav to-do start */ + /* MS_FIX for ccpu00123919*/ + noRbs = (noRbgs * cell->rbgSize) - rbgFiller; + if (dlSf->bwAlloced + noRbs > dlSf->bw) + { + if (--noRbgs == 0) + { + RETVOID; + } + noRbs = (noRbgs * cell->rbgSize) - rbgFiller; + } + /* Abhinav to-do end */ + + + + /* type0End would have been initially (during subfrm Init) at the bit position + * (cell->noOfRbgs - 1), 0 being the most significant. + * Getting DlAllocMsk for noRbgs and at the appropriate position */ + dlAllocMsk |= (((1 << noRbgs) - 1) << (31 - poolInfo->type0End)); + /* Move backwards the type0End pivot */ + poolInfo->type0End -= noRbgs; + /*MS_FIX for ccpu00123919*/ + /*noRbs = (noRbgs * cell->rbgSize) - rbgFiller;*/ + /* Update the bwAlloced field accordingly */ + poolInfo->bwAlloced += noRbs + dlSf->lstRbgDfct; + dlSf->bwAlloced += noRbs + dlSf->lstRbgDfct; + + /* Update Type0 Alloc Info */ + allocInfo->allocInfo.raType0.numDlAlloc = noRbgs; + allocInfo->allocInfo.raType0.dlAllocBitMask |= dlAllocMsk; + allocInfo->rbsAlloc = noRbs; + + /* Update Tb info for each scheduled TB */ + iTbs = allocInfo->tbInfo[0].iTbs; + noLyr = allocInfo->tbInfo[0].noLyr; + /* Fix for ccpu00123919: For a RETX TB the iTbs is irrelevant. + * RETX TB Size is same as Init TX TB Size */ + if (allocInfo->tbInfo[0].tbCb->txCntr) + { + allocInfo->tbInfo[0].bytesAlloc = + allocInfo->tbInfo[0].bytesReq; + } + else + { + allocInfo->tbInfo[0].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8; + } + + if (allocInfo->tbInfo[1].schdlngForTb) + { + iTbs = allocInfo->tbInfo[1].iTbs; + noLyr = allocInfo->tbInfo[1].noLyr; + /* Fix for ccpu00123919: For a RETX TB the iTbs is irrelevant + * RETX TB Size is same as Init TX TB Size */ + if (allocInfo->tbInfo[1].tbCb->txCntr) + { + allocInfo->tbInfo[1].bytesAlloc = + allocInfo->tbInfo[1].bytesReq; + } + else + { + allocInfo->tbInfo[1].bytesAlloc = + rgTbSzTbl[noLyr - 1][iTbs][noRbs - 1]/8;; + } + } + + /* The last RBG which can be smaller than the RBG size is consedered + * only for the first time allocation of TYPE0 UE */ + dlSf->lstRbgDfct = 0; + RETVOID; +} + +/** + * @brief Computes RNTP Info for a subframe. + * + * @details + * + * Function : rgSCHCmnNonDlfsDsfrRntpComp + * + * Processing Steps: + * - Computes RNTP info from individual pools. + * + * @param[in] RgSchDlSf *dlSf + * + * @return void + + **/ +#ifdef ANSI +PRIVATE void rgSCHCmnNonDlfsDsfrRntpComp +( +RgSchCellCb *cell, +RgSchDlSf *dlSf +) +#else +PRIVATE void rgSCHCmnNonDlfsDsfrRntpComp(cell, dlSf) +RgSchCellCb *cell; +RgSchDlSf *dlSf; +#endif +{ + PRIVATE U16 samples = 0; + U16 i; + U16 bwBytes = (dlSf->bw-1)/8; + RgrLoadInfIndInfo *rgrLoadInf; + U16 len; + U16 ret = ROK; + + TRC2(rgSCHCmnNonDlfsDsfrRntpComp); + + len = (dlSf->bw % 8 == 0) ? dlSf->bw/8 : dlSf->bw/8 + 1; + + /* RNTP info is ORed every TTI and the sample is stored in cell control block */ + for(i = 0; i <= bwBytes; i++) + { + cell->rntpAggrInfo.val[i] |= dlSf->rntpInfo.val[i]; + } + samples = samples + 1; + /* After every 1000 ms, the RNTP info will be sent to application to be further sent to all neighbouring eNB + informing them about the load indication for cell edge users */ + if(RG_SCH_MAX_RNTP_SAMPLES == samples) + { + /* ccpu00134492 */ + ret = rgSCHUtlAllocSBuf (cell->instIdx,(Data**)&rgrLoadInf, + sizeof(RgrLoadInfIndInfo)); + if (ret != ROK) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "Could not " + "allocate memory for sending LoadInfo"); + RETVOID; + } + + rgrLoadInf->u.rntpInfo.pres = cell->rntpAggrInfo.pres; + /* dsfr_pal_fixes ** 21-March-2013 ** SKS */ + rgrLoadInf->u.rntpInfo.len = len; + + /* dsfr_pal_fixes ** 21-March-2013 ** SKS */ + rgrLoadInf->u.rntpInfo.val = cell->rntpAggrInfo.val; + rgrLoadInf->cellId = cell->cellId; + + /* dsfr_pal_fixes ** 22-March-2013 ** SKS */ + rgrLoadInf->bw = dlSf->bw; + rgrLoadInf->type = RGR_SFR; + + ret = rgSCHUtlRgrLoadInfInd(cell, rgrLoadInf); + if(ret == RFAILED) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHCmnNonDlfsDsfrRntpComp():" + "rgSCHUtlRgrLoadInfInd() returned RFAILED"); + } + + cmMemset(cell->rntpAggrInfo.val,0,len); + samples = 0; + } + } +/* LTE_ADV_FLAG_REMOVED_END */ + +/* LTE_ADV_FLAG_REMOVED_START */ +/** + * @brief Performs RB allocation per UE from a pool. + * + * @details + * + * Function : rgSCHCmnSFRNonDlfsUeRbAlloc + * + * Processing Steps: + * - Allocate consecutively available RBs. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlSf *dlSf + * @param[out] U8 *isDlBwAvail + * + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnSFRNonDlfsUeRbAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *dlSf, +U8 *isDlBwAvail +) +#else +PRIVATE S16 rgSCHCmnSFRNonDlfsUeRbAlloc(cell, ue, dlSf, isDlBwAvail) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlSf *dlSf; +U8 *isDlBwAvail; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *dlUe; + Bool isUECellEdge; + RgSchSFRPoolInfo *sfrpoolInfo = NULLP; + + TRC2(rgSCHCmnSFRNonDlfsUeRbAlloc); + + isUECellEdge = RG_SCH_CMN_IS_UE_CELL_EDGE(ue); + + dlUe = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + *isDlBwAvail = TRUE; + + /*Find which pool is available for this UE*/ + if (rgSCHCmnNonDlfsSFRBwAvlbl(cell, &sfrpoolInfo, dlSf, allocInfo, isUECellEdge) != TRUE) + { + /* SFR_FIX - If this is CE UE there may be BW available in CC Pool + So CC UEs will be scheduled */ + if (isUECellEdge) + { + *isDlBwAvail = TRUE; + } + else + { + *isDlBwAvail = FALSE; + } + RETVALUE(RFAILED); + } + + if (dlUe->proc->tbInfo[0].isAckNackDtx == TFU_HQFDB_DTX || dlUe->proc->tbInfo[1].isAckNackDtx) + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, dlUe->mimoInfo.cwInfo[0].cqi, allocInfo->dciFormat, TRUE); + } + else + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, dlUe->mimoInfo.cwInfo[0].cqi, allocInfo->dciFormat,FALSE); + } + + if (!(allocInfo->pdcch)) + { + /* Returning ROK since PDCCH might be available for another UE and further allocations could be done */ + RETVALUE(RFAILED); + } + +#ifdef LTEMAC_SPS + allocInfo->rnti = ue->ueId; +#endif + + if (allocInfo->raType == RG_SCH_CMN_RA_TYPE2) + { + allocInfo->allocInfo.raType2.isLocal = TRUE; + /* rg004.201 patch - ccpu00109921 fix end */ + /* MS_FIX for ccpu00123918*/ + allocInfo->allocInfo.raType2.rbStart = (U8)sfrpoolInfo->type2Start; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + /* rg007.201 - Changes for MIMO feature addition */ + /* rg008.201 - Removed dependency on MIMO compile-time flag */ + rgSCHCmnNonDlfsUpdSFRPoolTyp2Alloc(cell, ue, dlSf, sfrpoolInfo, \ + allocInfo->allocInfo.raType2.rbStart, \ + allocInfo->allocInfo.raType2.numRb); + allocInfo->rbsAlloc = allocInfo->rbsReq; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + } + else if (allocInfo->raType == RG_SCH_CMN_RA_TYPE0) + { + rgSCHCmnNonDlfsSFRPoolType0Alloc(cell, dlSf, sfrpoolInfo, allocInfo); + } +#ifndef LTE_TDD +#ifdef DEBUGP + rgSCHCmnFindCodeRate(cell,dlSf,allocInfo,0); + if(allocInfo->tbInfo[1].schdlngForTb == TRUE) + { + rgSCHCmnFindCodeRate(cell,dlSf,allocInfo,1); + } +#endif +#endif + +#if defined(LTEMAC_SPS) + /* Update the sub-frame with new allocation */ + dlSf->bwAlloced += allocInfo->rbsReq; +#endif + + RETVALUE(ROK); +} +/* LTE_ADV_FLAG_REMOVED_END */ +#endif /* LTE_TDD */ + +/** + * @brief Performs RB allocation per UE for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsUeRbAlloc + * + * Processing Steps: + * - Allocate consecutively available RBs. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlSf *dlSf + * @param[out] U8 *isDlBwAvail + * + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsUeRbAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlSf *dlSf, +U8 *isDlBwAvail +) +#else +PRIVATE S16 rgSCHCmnNonDlfsUeRbAlloc(cell, ue, dlSf, isDlBwAvail) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlSf *dlSf; +U8 *isDlBwAvail; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *dlUe; +#ifdef LAA_DBG + U32 dbgRbsReq = 0; +#endif + TRC2(rgSCHCmnNonDlfsUeRbAlloc); + +#ifdef RG_5GTF + RgSch5gtfUeCb *ue5gtfCb = &(ue->ue5gtfCb); + RgSchSfBeamInfo *beamInfo = &(dlSf->sfBeamInfo[ue5gtfCb->BeamId]); +#endif + dlUe = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + *isDlBwAvail = TRUE; + + if(beamInfo->totVrbgAllocated > MAX_5GTF_VRBG) + { + RLOG_ARG1(L_ERROR ,DBG_CELLID,cell->cellId, + "5GTF_ERROR : vrbg allocated > 25 :ue (%u)", + ue->ueId); + printf("5GTF_ERROR vrbg allocated > 25\n"); + RETVALUE(RFAILED); + } + + if (dlUe->proc->tbInfo[0].isAckNackDtx == TFU_HQFDB_DTX + || dlUe->proc->tbInfo[1].isAckNackDtx) + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, dlUe->mimoInfo.cwInfo[0].cqi, allocInfo->dciFormat, TRUE); + } + else + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ue, dlSf, dlUe->mimoInfo.cwInfo[0].cqi, allocInfo->dciFormat,FALSE); + } + if (!(allocInfo->pdcch)) + { + /* Returning ROK since PDCCH might be available for another UE and + * further allocations could be done */ + RLOG_ARG1(L_ERROR ,DBG_CELLID,cell->cellId, + "5GTF_ERROR : PDCCH allocation failed :ue (%u)", + ue->ueId); + printf("5GTF_ERROR PDCCH allocation failed\n"); + RETVALUE(RFAILED); + } +#ifdef RG_5GTF + //maxPrb = RGSCH_MIN((allocInfo->vrbgReq * MAX_5GTF_VRBG_SIZE), ue5gtfCb->maxPrb); + //maxPrb = RGSCH_MIN(maxPrb, + //((beamInfo->totVrbgAvail - beamInfo->vrbgStart)* MAX_5GTF_VRBG_SIZE))); + //TODO_SID Need to check for vrbg available after scheduling for same beam. + allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart = beamInfo->vrbgStart; + allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg = allocInfo->vrbgReq; + //TODO_SID: Setting for max TP + allocInfo->tbInfo[0].tbCb->dlGrnt.xPDSCHRange = 1; + allocInfo->tbInfo[0].tbCb->dlGrnt.rbAssign = rgSCHCmnCalcRiv(MAX_5GTF_VRBG, + allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart, allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg); + allocInfo->tbInfo[0].tbCb->dlGrnt.SCID = 0; + allocInfo->tbInfo[0].tbCb->dlGrnt.dciFormat = allocInfo->dciFormat; + //Filling temporarily + allocInfo->tbInfo[0].tbCb->dlGrnt.rbStrt = (allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart * MAX_5GTF_VRBG_SIZE); + allocInfo->tbInfo[0].tbCb->dlGrnt.numRb = (allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg * MAX_5GTF_VRBG_SIZE); + + beamInfo->vrbgStart += allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg; + beamInfo->totVrbgAllocated += allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; +#endif + + RETVALUE(ROK); +} + +#ifdef RGR_V1 +/** + * @brief Performs RB allocation for Msg4 for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsCcchSduAlloc + * + * Processing Steps: + * - For each element in the list, Call rgSCHCmnNonDlfsCcchSduRbAlloc(). + * - If allocation is successful, add the ueCb to scheduled list of CCCH + * SDU. + * - else, add UeCb to non-scheduled list. + * + * @param[in] RgSchCellCb *cell + * @param[in, out] RgSchCmnCcchSduRbAlloc *allocInfo + * @param[in] U8 isRetx + * + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsCcchSduAlloc +( +RgSchCellCb *cell, +RgSchCmnCcchSduRbAlloc *allocInfo, +U8 isRetx +) +#else +PRIVATE Void rgSCHCmnNonDlfsCcchSduAlloc(cell, allocInfo, isRetx) +RgSchCellCb *cell; +RgSchCmnCcchSduRbAlloc *allocInfo; +U8 isRetx; +#endif +{ + S16 ret; + CmLListCp *ccchSduLst = NULLP; + CmLListCp *schdCcchSduLst = NULLP; + CmLListCp *nonSchdCcchSduLst = NULLP; + CmLList *schdLnkNode = NULLP; + CmLList *toBeSchdLnk = NULLP; + RgSchDlSf *dlSf = allocInfo->ccchSduDlSf; + RgSchUeCb *ueCb = NULLP; + RgSchDlHqProcCb *hqP = NULLP; + TRC2(rgSCHCmnNonDlfsCcchSduAlloc); + + if (isRetx) + { + /* Initialize re-transmitting lists */ + ccchSduLst = &(allocInfo->ccchSduRetxLst); + schdCcchSduLst = &(allocInfo->schdCcchSduRetxLst); + nonSchdCcchSduLst = &(allocInfo->nonSchdCcchSduRetxLst); + } + else + { + /* Initialize transmitting lists */ + ccchSduLst = &(allocInfo->ccchSduTxLst); + schdCcchSduLst = &(allocInfo->schdCcchSduTxLst); + nonSchdCcchSduLst = &(allocInfo->nonSchdCcchSduTxLst); + } + + /* Perform allocaations for the list */ + toBeSchdLnk = cmLListFirst(ccchSduLst); + for (; toBeSchdLnk; toBeSchdLnk = toBeSchdLnk->next) + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + ueCb = hqP->hqE->ue; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + ret = rgSCHCmnNonDlfsCcchSduRbAlloc(cell, ueCb, dlSf); + if (ret != ROK) + { + /* Allocation failed: Add remaining MSG4 nodes to non-scheduled + * list and return */ + do + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + ueCb = hqP->hqE->ue; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + cmLListAdd2Tail(nonSchdCcchSduLst, schdLnkNode); + toBeSchdLnk = toBeSchdLnk->next; + } while(toBeSchdLnk); + RETVOID; + } + + /* Allocation successful: Add UE to the scheduled list */ + cmLListAdd2Tail(schdCcchSduLst, schdLnkNode); + } + + + RETVOID; +} + +/** + * @brief Performs RB allocation for CcchSdu for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsCcchSduRbAlloc + * + * Processing Steps: + * - Fetch PDCCH + * - Allocate consecutively available RBs + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ueCb + * @param[in] RgSchDlSf *dlSf + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsCcchSduRbAlloc +( +RgSchCellCb *cell, +RgSchUeCb *ueCb, +RgSchDlSf *dlSf +) +#else +PRIVATE S16 rgSCHCmnNonDlfsCcchSduRbAlloc(cell, ueCb, dlSf) +RgSchCellCb *cell; +RgSchUeCb *ueCb; +RgSchDlSf *dlSf; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell); + + TRC2(rgSCHCmnNonDlfsCcchSduRbAlloc); + + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ueCb,cell); + + /* [ccpu00138802]-MOD-If Bw is less than required, return fail + It will be allocated in next TTI */ +#ifdef LTEMAC_SPS + if ((dlSf->spsAllocdBw >= cell->spsBwRbgInfo.numRbs) && + (dlSf->bwAlloced == dlSf->bw)) +#else + if((dlSf->bwAlloced == dlSf->bw) || + (allocInfo->rbsReq > (dlSf->bw - dlSf->bwAlloced))) +#endif + { + RETVALUE(RFAILED); + } + /* Retrieve PDCCH */ + /* DTX Changes: One Variable is passed to check whether it is DTX or Not */ + if (ueDl->proc->tbInfo[0].isAckNackDtx == TFU_HQFDB_DTX) + { + /* allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, dlSf, y, ueDl->cqi, + * TFU_DCI_FORMAT_1A, TRUE);*/ + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ueCb, dlSf, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_1A, TRUE); + } + else + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, ueCb, dlSf, ueDl->mimoInfo.cwInfo[0].cqi, TFU_DCI_FORMAT_1A, FALSE); + } + if (!(allocInfo->pdcch)) + { + /* Returning RFAILED since PDCCH not available for any CCCH allocations */ + RETVALUE(RFAILED); + } + + /* Update allocation information */ + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + allocInfo->allocInfo.raType2.isLocal = TRUE; + + /*Fix for ccpu00123918*/ + /* Push this harq process back to the free queue */ + allocInfo->allocInfo.raType2.rbStart = (U8)dlSf->type2Start; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + allocInfo->rbsAlloc = allocInfo->rbsReq; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + /* Update the sub-frame with new allocation */ + /* ccpu00129469 */ + /* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD + if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE) + { + rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc(cell, dlSf, + allocInfo->allocInfo.raType2.rbStart, + allocInfo->allocInfo.raType2.numRb); + } + else +#endif /* end of ifndef LTE_TDD*/ + { + rgSCHCmnNonDlfsUpdTyp2Alloc(cell, dlSf, + allocInfo->allocInfo.raType2.rbStart, + allocInfo->allocInfo.raType2.numRb); + } + + /* LTE_ADV_FLAG_REMOVED_END */ + /* ccpu00131941 - bwAlloced is updated from SPS bandwidth */ + + + RETVALUE(ROK); +} +#endif + +/** + * @brief Performs RB allocation for Msg4 for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsMsg4RbAlloc + * + * Processing Steps: + * - Fetch PDCCH + * - Allocate consecutively available RBs + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchRaCb *raCb + * @param[in] RgSchDlSf *dlSf + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnNonDlfsMsg4RbAlloc +( +RgSchCellCb *cell, +RgSchRaCb *raCb, +RgSchDlSf *dlSf +) +#else +PRIVATE S16 rgSCHCmnNonDlfsMsg4RbAlloc(cell, raCb, dlSf) +RgSchCellCb *cell; +RgSchRaCb *raCb; +RgSchDlSf *dlSf; +#endif +{ + RgSchDlRbAlloc *allocInfo; + TRC2(rgSCHCmnNonDlfsMsg4RbAlloc); + + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_RACB(raCb); + +#ifdef RG_5GTF + RgSchSfBeamInfo *beamInfo = &(dlSf->sfBeamInfo[0]); + if(beamInfo->totVrbgAllocated > MAX_5GTF_VRBG) + { + RLOG_ARG1(L_ERROR ,DBG_CELLID,cell->cellId, + "5GTF_ERROR : vrbg allocated > 25 :ue (%u)", + raCb->ue->ueId); + printf("5GTF_ERROR vrbg allocated > 25\n"); + RETVALUE(RFAILED); + } +#endif +#ifdef LTEMAC_SPS + if ((dlSf->spsAllocdBw >= cell->spsBwRbgInfo.numRbs) && + (dlSf->bwAlloced == dlSf->bw)) +#else + if((dlSf->bwAlloced == dlSf->bw) || + (allocInfo->rbsReq > (dlSf->bw - dlSf->bwAlloced))) +#endif + { + + RETVALUE(RFAILED); + } + + /* DTX Changes: One Variable is passed to check whether it is DTX or Not */ + if (raCb->dlHqE->msg4Proc->tbInfo[0].isAckNackDtx == TFU_HQFDB_DTX) + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, raCb->ue, dlSf, raCb->ccchCqi, TFU_DCI_FORMAT_B1, TRUE); + } + else + { + allocInfo->pdcch = rgSCHCmnPdcchAlloc(cell, raCb->ue, dlSf, raCb->ccchCqi, TFU_DCI_FORMAT_B1, FALSE); + } + if (!(allocInfo->pdcch)) + { + /* Returning RFAILED since PDCCH not available for any CCCH allocations */ + RETVALUE(RFAILED); + } + +#ifndef RG_5GTF + /* SR_RACH_STATS : MSG4 TX Failed */ + allocInfo->pdcch->dci.u.format1aInfo.t.pdschInfo.isTBMsg4 = TRUE; + + /* Update allocation information */ + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + allocInfo->allocInfo.raType2.isLocal = TRUE; + + + /*Fix for ccpu00123918*/ + allocInfo->allocInfo.raType2.rbStart = (U8)dlSf->type2Start; + allocInfo->allocInfo.raType2.numRb = allocInfo->rbsReq; + /* LTE_ADV_FLAG_REMOVED_START */ +#ifndef LTE_TDD + if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE) + { + rgSCHCmnNonDlfsSFRCmnChannelUpdTyp2Alloc(cell, dlSf, \ + allocInfo->allocInfo.raType2.rbStart, \ + allocInfo->allocInfo.raType2.numRb); + } + else +#endif /* end of ifndef LTE_TDD */ + { + rgSCHCmnNonDlfsUpdTyp2Alloc(cell, dlSf, \ + allocInfo->allocInfo.raType2.rbStart, \ + allocInfo->allocInfo.raType2.numRb); + } + /* LTE_ADV_FLAG_REMOVED_END */ + + allocInfo->rbsAlloc = allocInfo->rbsReq; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + +#else + + allocInfo->pdcch->dci.u.format1aInfo.t.pdschInfo.isTBMsg4 = TRUE; + + allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart = beamInfo->vrbgStart; + allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg = allocInfo->vrbgReq; + + /* Update allocation information */ + allocInfo->dciFormat = TFU_DCI_FORMAT_B1; + + allocInfo->tbInfo[0].tbCb->dlGrnt.xPDSCHRange = 1; + allocInfo->tbInfo[0].tbCb->dlGrnt.rbAssign = rgSCHCmnCalcRiv(MAX_5GTF_VRBG, + allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart, allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg); + + allocInfo->tbInfo[0].tbCb->dlGrnt.rbStrt = (allocInfo->tbInfo[0].tbCb->dlGrnt.vrbgStart * MAX_5GTF_VRBG_SIZE); + allocInfo->tbInfo[0].tbCb->dlGrnt.numRb = (allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg * MAX_5GTF_VRBG_SIZE); + + + beamInfo->vrbgStart += allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg; + beamInfo->totVrbgAllocated += allocInfo->tbInfo[0].tbCb->dlGrnt.numVrbg; + allocInfo->tbInfo[0].bytesAlloc = allocInfo->tbInfo[0].bytesReq; + +#endif + + RETVALUE(ROK); +} + +/** + * @brief Performs RB allocation for Msg4 lists of frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsMsg4Alloc + * + * Processing Steps: + * - For each element in the list, Call rgSCHCmnNonDlfsMsg4RbAlloc(). + * - If allocation is successful, add the raCb to scheduled list of MSG4. + * - else, add RaCb to non-scheduled list. + * + * @param[in] RgSchCellCb *cell + * @param[in, out] RgSchCmnMsg4RbAlloc *allocInfo + * @param[in] U8 isRetx + * + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsMsg4Alloc +( +RgSchCellCb *cell, +RgSchCmnMsg4RbAlloc *allocInfo, +U8 isRetx +) +#else +PRIVATE Void rgSCHCmnNonDlfsMsg4Alloc(cell, allocInfo, isRetx) +RgSchCellCb *cell; +RgSchCmnMsg4RbAlloc *allocInfo; +U8 isRetx; +#endif +{ + S16 ret; + CmLListCp *msg4Lst = NULLP; + CmLListCp *schdMsg4Lst = NULLP; + CmLListCp *nonSchdMsg4Lst = NULLP; + CmLList *schdLnkNode = NULLP; + CmLList *toBeSchdLnk = NULLP; + RgSchDlSf *dlSf = allocInfo->msg4DlSf; + RgSchRaCb *raCb = NULLP; + RgSchDlHqProcCb *hqP = NULLP; + TRC2(rgSCHCmnNonDlfsMsg4Alloc); + + if (isRetx) + { + /* Initialize re-transmitting lists */ + msg4Lst = &(allocInfo->msg4RetxLst); + schdMsg4Lst = &(allocInfo->schdMsg4RetxLst); + nonSchdMsg4Lst = &(allocInfo->nonSchdMsg4RetxLst); + } + else + { + /* Initialize transmitting lists */ + msg4Lst = &(allocInfo->msg4TxLst); + schdMsg4Lst = &(allocInfo->schdMsg4TxLst); + nonSchdMsg4Lst = &(allocInfo->nonSchdMsg4TxLst); + } + + /* Perform allocaations for the list */ + toBeSchdLnk = cmLListFirst(msg4Lst); + for (; toBeSchdLnk; toBeSchdLnk = toBeSchdLnk->next) + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + raCb = hqP->hqE->raCb; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + ret = rgSCHCmnNonDlfsMsg4RbAlloc(cell, raCb, dlSf); + if (ret != ROK) + { + /* Allocation failed: Add remaining MSG4 nodes to non-scheduled + * list and return */ + do + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + raCb = hqP->hqE->raCb; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + cmLListAdd2Tail(nonSchdMsg4Lst, schdLnkNode); + toBeSchdLnk = toBeSchdLnk->next; + } while(toBeSchdLnk); + RETVOID; + } + + /* Allocation successful: Add UE to the scheduled list */ + cmLListAdd2Tail(schdMsg4Lst, schdLnkNode); + if (isRetx) + { + } + } + + + RETVOID; +} + +/** + * @brief Performs RB allocation for the list of UEs of a frequency + * non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsDedRbAlloc + * + * Processing Steps: + * - For each element in the list, Call rgSCHCmnNonDlfsUeRbAlloc(). + * - If allocation is successful, add the ueCb to scheduled list of UEs. + * - else, add ueCb to non-scheduled list of UEs. + * + * @param[in] RgSchCellCb *cell + * @param[in, out] RgSchCmnUeRbAlloc *allocInfo + * @param[in] CmLListCp *ueLst, + * @param[in, out] CmLListCp *schdHqPLst, + * @param[in, out] CmLListCp *nonSchdHqPLst + * + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnNonDlfsDedRbAlloc +( +RgSchCellCb *cell, +RgSchCmnUeRbAlloc *allocInfo, +CmLListCp *ueLst, +CmLListCp *schdHqPLst, +CmLListCp *nonSchdHqPLst +) +#else +PUBLIC Void rgSCHCmnNonDlfsDedRbAlloc(cell, allocInfo, ueLst, + schdHqPLst, nonSchdHqPLst) +RgSchCellCb *cell; +RgSchCmnUeRbAlloc *allocInfo; +CmLListCp *ueLst; +CmLListCp *schdHqPLst; +CmLListCp *nonSchdHqPLst; +#endif +{ + S16 ret; + CmLList *schdLnkNode = NULLP; + CmLList *toBeSchdLnk = NULLP; + RgSchDlSf *dlSf = allocInfo->dedDlSf; + RgSchUeCb *ue = NULLP; + RgSchDlHqProcCb *hqP = NULLP; + U8 isDlBwAvail; + TRC2(rgSCHCmnNonDlfsDedRbAlloc); + + + /* Perform allocaations for the list */ + toBeSchdLnk = cmLListFirst(ueLst); + for (; toBeSchdLnk; toBeSchdLnk = toBeSchdLnk->next) + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + ue = hqP->hqE->ue; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + + ret = rgSCHCmnNonDlfsUeRbAlloc(cell, ue, dlSf, &isDlBwAvail); + if (!isDlBwAvail) + { + /* Allocation failed: Add remaining UEs to non-scheduled + * list and return */ + do + { + hqP = (RgSchDlHqProcCb *)(toBeSchdLnk->node); + ue = hqP->hqE->ue; + schdLnkNode = &hqP->schdLstLnk; + RG_SCH_CMN_INIT_SCHD_LNK(schdLnkNode, hqP); + cmLListAdd2Tail(nonSchdHqPLst, schdLnkNode); + toBeSchdLnk = toBeSchdLnk->next; + } while(toBeSchdLnk); + break; + } + + if (ret == ROK) + { +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.dl5gtfRbAllocPass++; +#endif + /* Allocation successful: Add UE to the scheduled list */ + cmLListAdd2Tail(schdHqPLst, schdLnkNode); + } + else + { +#if defined (TENB_STATS) && defined (RG_5GTF) + cell->tenbStats->sch.dl5gtfRbAllocFail++; +#endif + /* Allocation failed : Add UE to the non-scheduled list */ + printf("5GTF_ERROR Dl rb alloc failed adding nonSchdHqPLst\n"); + cmLListAdd2Tail(nonSchdHqPLst, schdLnkNode); + } + } + + RETVOID; +} + +/** + * @brief Handles RB allocation for frequency non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsRbAlloc + * + * Invoking Module Processing: + * - SCH shall invoke this if downlink frequency selective is disabled for + * the cell for RB allocation. + * - MAX C/I/PFS/RR shall provide the requiredBytes, required RBs + * estimate and subframe for each allocation to be made to SCH. + * + * Processing Steps: + * - Allocate sequentially for common channels. + * - For transmitting and re-transmitting UE list. + * - For each UE: + * - Perform wide-band allocations for UE in increasing order of + * frequency. + * - Determine Imcs for the allocation. + * - Determine RA type. + * - Determine DCI format. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + **/ + +#ifdef ANSI +PUBLIC Void rgSCHCmnNonDlfsRbAlloc +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PUBLIC Void rgSCHCmnNonDlfsRbAlloc(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + U8 raRspCnt = 0; + RgSchDlRbAlloc *reqAllocInfo; + TRC2(rgSCHCmnNonDlfsRbAlloc); + + /* Allocate for MSG4 retransmissions */ + if (allocInfo->msg4Alloc.msg4RetxLst.count) + { + printf("5GTF_ERROR rgSCHCmnNonDlfsMsg4Alloc RetxLst\n"); + rgSCHCmnNonDlfsMsg4Alloc(cell, &(allocInfo->msg4Alloc), TRUE); + } + + /* Allocate for MSG4 transmissions */ + /* Assuming all the nodes in the list need allocations: rbsReq is valid */ + if (allocInfo->msg4Alloc.msg4TxLst.count) + { + printf("5GTF_ERROR rgSCHCmnNonDlfsMsg4Alloc txLst\n"); + rgSCHCmnNonDlfsMsg4Alloc(cell, &(allocInfo->msg4Alloc), FALSE); + } +#ifdef RGR_V1 + /* Allocate for CCCH SDU (received after guard timer expiry) + * retransmissions */ + if (allocInfo->ccchSduAlloc.ccchSduRetxLst.count) + { + printf("5GTF_ERROR rgSCHCmnNonDlfsCcchSduAlloc\n"); + rgSCHCmnNonDlfsCcchSduAlloc(cell, &(allocInfo->ccchSduAlloc), TRUE); + } + + /* Allocate for CCCD SDU transmissions */ + /* Allocate for CCCH SDU (received after guard timer expiry) transmissions */ + if (allocInfo->ccchSduAlloc.ccchSduTxLst.count) + { + printf("5GTF_ERROR rgSCHCmnNonDlfsCcchSduAlloc\n"); + rgSCHCmnNonDlfsCcchSduAlloc(cell, &(allocInfo->ccchSduAlloc), FALSE); + } +#endif + + /* Allocate for Random access response */ + for (raRspCnt = 0; raRspCnt < RG_SCH_CMN_MAX_CMN_PDCCH; ++raRspCnt) + { + /* Assuming that the requests will be filled in sequentially */ + reqAllocInfo = &(allocInfo->raRspAlloc[raRspCnt]); + if (!reqAllocInfo->rbsReq) + { + break; + } + printf("5GTF_ERROR calling RAR rgSCHCmnNonDlfsCmnRbAlloc\n"); + // if ((rgSCHCmnNonDlfsCmnRbAlloc(cell, reqAllocInfo)) != ROK) + if ((rgSCHCmnNonDlfsCmnRbAllocRar(cell, reqAllocInfo)) != ROK) + { + break; + } + } + + /* Allocate for RETX+TX UEs */ + if(allocInfo->dedAlloc.txRetxHqPLst.count) + { + printf("5GTF_ERROR TX RETX rgSCHCmnNonDlfsDedRbAlloc\n"); + rgSCHCmnNonDlfsDedRbAlloc(cell, &(allocInfo->dedAlloc), + &(allocInfo->dedAlloc.txRetxHqPLst), + &(allocInfo->dedAlloc.schdTxRetxHqPLst), + &(allocInfo->dedAlloc.nonSchdTxRetxHqPLst)); + } + + if((allocInfo->dedAlloc.retxHqPLst.count)) + { + rgSCHCmnNonDlfsDedRbAlloc(cell, &(allocInfo->dedAlloc), + &(allocInfo->dedAlloc.retxHqPLst), + &(allocInfo->dedAlloc.schdRetxHqPLst), + &(allocInfo->dedAlloc.nonSchdRetxHqPLst)); + } + + /* Allocate for transmitting UEs */ + if((allocInfo->dedAlloc.txHqPLst.count)) + { + rgSCHCmnNonDlfsDedRbAlloc(cell, &(allocInfo->dedAlloc), + &(allocInfo->dedAlloc.txHqPLst), + &(allocInfo->dedAlloc.schdTxHqPLst), + &(allocInfo->dedAlloc.nonSchdTxHqPLst)); + } + { + RgSchCmnCell *cmnCell = RG_SCH_CMN_GET_CELL(cell); + if ((allocInfo->dedAlloc.txRetxHqPLst.count + + allocInfo->dedAlloc.retxHqPLst.count + + allocInfo->dedAlloc.txHqPLst.count) > + cmnCell->dl.maxUePerDlSf) + { +#ifndef ALIGN_64BIT + RGSCHDBGERRNEW(cell->instIdx,(rgSchPBuf(cell->instIdx),"UEs selected by" + " scheduler exceed maximumUePerDlSf(%u)tx-retx %ld retx %ld tx %ld\n", + cmnCell->dl.maxUePerDlSf, allocInfo->dedAlloc.txRetxHqPLst.count, + allocInfo->dedAlloc.retxHqPLst.count, + allocInfo->dedAlloc.txHqPLst.count)); +#else + RGSCHDBGERRNEW(cell->instIdx,(rgSchPBuf(cell->instIdx),"UEs selected by" + " scheduler exceed maximumUePerDlSf(%u)tx-retx %d retx %d tx %d\n", + cmnCell->dl.maxUePerDlSf, allocInfo->dedAlloc.txRetxHqPLst.count, + allocInfo->dedAlloc.retxHqPLst.count, + allocInfo->dedAlloc.txHqPLst.count)); +#endif + } + } +#ifndef LTE_TDD + /* LTE_ADV_FLAG_REMOVED_START */ + if(cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE) + { + printf("5GTF_ERROR RETX rgSCHCmnNonDlfsDsfrRntpComp\n"); + rgSCHCmnNonDlfsDsfrRntpComp(cell, allocInfo->dedAlloc.dedDlSf); + } + /* LTE_ADV_FLAG_REMOVED_END */ +#endif /* LTE_TDD */ + RETVOID; +} + +/*********************************************************** + * + * Func : rgSCHCmnCalcRiv + * + * Desc : This function calculates RIV. + * + * Ret : None. + * + * Notes: None. + * + * File : rg_sch_utl.c + * + **********************************************************/ +#ifdef LTEMAC_SPS +#ifdef ANSI +PUBLIC U32 rgSCHCmnCalcRiv +( +U8 bw, +U8 rbStart, +U8 numRb +) +#else +PUBLIC U32 rgSCHCmnCalcRiv(bw, rbStart, numRb) +U8 bw; +U8 rbStart; +U8 numRb; +#endif +#else +#ifdef ANSI +PUBLIC U32 rgSCHCmnCalcRiv +( +U8 bw, +U8 rbStart, +U8 numRb +) +#else +PUBLIC U32 rgSCHCmnCalcRiv(bw, rbStart, numRb) +U8 bw; +U8 rbStart; +U8 numRb; +#endif +#endif +{ + U8 numRbMinus1 = numRb - 1; + U32 riv; + + TRC2(rgSCHCmnCalcRiv); + + if (numRbMinus1 <= bw/2) + { + riv = bw * numRbMinus1 + rbStart; + } + else + { + riv = bw * (bw - numRbMinus1) + (bw - rbStart - 1); + } + RETVALUE(riv); +} /* rgSCHCmnCalcRiv */ + +#ifdef LTE_TDD +/** + * @brief This function allocates and copies the RACH response scheduling + * related information into cell control block. + * + * @details + * + * Function: rgSCHCmnDlCpyRachInfo + * Purpose: This function allocates and copies the RACH response + * scheduling related information into cell control block + * for each DL subframe. + * + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @param[in] RgSchTddRachRspLst rachRspLst[][RGSCH_NUM_SUB_FRAMES] + * @param[in] U8 raArrSz + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlCpyRachInfo +( +RgSchCellCb *cell, +RgSchTddRachRspLst rachRspLst[][RGSCH_NUM_SUB_FRAMES], +U8 raArrSz +) +#else +PRIVATE S16 rgSCHCmnDlCpyRachInfo(cell, rachRspLst, raArrSz) +RgSchCellCb *cell; +RgSchTddRachRspLst rachRspLst[][RGSCH_NUM_SUB_FRAMES]; +U8 raArrSz; +#endif +{ + U8 ulDlCfgIdx = cell->ulDlCfgIdx; + U8 sfNum; + S16 sfnIdx; + U16 subfrmIdx; + U8 numRfs; + U8 numSubfrms; + U8 sfcount; + S16 ret; + + TRC2(rgSCHCmnDlCpyRachInfo); + + /* Allocate RACH response information for each DL + * subframe in a radio frame */ + ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&cell->rachRspLst, + rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1] * + sizeof(RgSchTddRachRspLst)); + if (ret != ROK) + { + RETVALUE(ret); + } + + for(sfnIdx=raArrSz-1; sfnIdx>=0; sfnIdx--) + { + for(subfrmIdx=0; subfrmIdx < RGSCH_NUM_SUB_FRAMES; subfrmIdx++) + { + subfrmIdx = rgSchTddHighDlSubfrmIdxTbl[ulDlCfgIdx][subfrmIdx]; + if(subfrmIdx == RGSCH_NUM_SUB_FRAMES) + { + break; + } + + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rachRspLst[sfnIdx],subfrmIdx); + numSubfrms = + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].numSubfrms; + + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, rgSchTddNumDlSubfrmTbl[ulDlCfgIdx],subfrmIdx); + sfNum = rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][subfrmIdx]-1; + numRfs = cell->rachRspLst[sfNum].numRadiofrms; + /* For each DL subframe in which RACH response can + * be sent is updated */ + if(numSubfrms > 0) + { + cell->rachRspLst[sfNum].rachRsp[numRfs].sfnOffset = + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].sfnOffset; + for(sfcount=0; sfcount < numSubfrms; sfcount++) + { + cell->rachRspLst[sfNum].rachRsp[numRfs].\ + subframe[sfcount] = + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].\ + subframe[sfcount]; + } + cell->rachRspLst[sfNum].rachRsp[numRfs].numSubfrms = + rachRspLst[sfnIdx][subfrmIdx].rachRsp[0].numSubfrms; + cell->rachRspLst[sfNum].numRadiofrms++; + } + + /* Copy the subframes to be deleted at ths subframe */ + numSubfrms = + rachRspLst[sfnIdx][subfrmIdx].delInfo.numSubfrms; + if(numSubfrms > 0) + { + cell->rachRspLst[sfNum].delInfo.sfnOffset = + rachRspLst[sfnIdx][subfrmIdx].delInfo.sfnOffset; + for(sfcount=0; sfcount < numSubfrms; sfcount++) + { + cell->rachRspLst[sfNum].delInfo.subframe[sfcount] = + rachRspLst[sfnIdx][subfrmIdx].delInfo.subframe[sfcount]; + } + cell->rachRspLst[sfNum].delInfo.numSubfrms = + rachRspLst[sfnIdx][subfrmIdx].delInfo.numSubfrms; + } + } + } + RETVALUE(ROK); +} +#endif +/** + * @brief This function determines the iTbs based on the new CFI, + * CQI and BLER based delta iTbs + * + * @details + * + * Function: rgSchCmnFetchItbs + * Purpose: Fetch the new iTbs when CFI changes. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlUe *ueDl + * @param[in] U8 cqi + * + * @return S32 iTbs + * + **/ +#ifdef LTE_TDD +#ifdef ANSI +PRIVATE S32 rgSchCmnFetchItbs +( +RgSchCellCb *cell, +RgSchCmnDlUe *ueDl, +RgSchDlSf *subFrm, +U8 cqi, +U8 cfi, +U8 cwIdx, +U8 noLyr +) +#else +PRIVATE S32 rgSchCmnFetchItbs (cell, ueDl, subFrm, cqi, cfi, cwIdx, noLyr) +RgSchCellCb *cell; +RgSchCmnDlUe *ueDl; +RgSchDlSf *subFrm; +U8 cqi; +U8 cfi; +U8 cwIdx; +U8 noLyr; +#endif +#else +#ifdef ANSI +PRIVATE S32 rgSchCmnFetchItbs +( +RgSchCellCb *cell, +RgSchCmnDlUe *ueDl, +U8 cqi, +U8 cfi, +U8 cwIdx, +U8 noLyr +) +#else +PRIVATE S32 rgSchCmnFetchItbs (cell, ueDl, cqi, cfi, cwIdx, noLyr) +RgSchCellCb *cell; +RgSchCmnDlUe *ueDl; +U8 cqi; +U8 cfi; +U8 cwIdx; +U8 noLyr; +#endif +#endif +{ + + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + S32 iTbs = 0; + + TRC2(rgSchCmnFetchItbs); + +#ifdef LTE_TDD + /* Special Handling for Spl Sf when CFI is 3 as + * CFI in Spl Sf will be max 2 */ + if(subFrm->sfType == RG_SCH_SPL_SF_DATA) + { + if((cellDl->currCfi == 3) || + ((cell->bwCfg.dlTotalBw <= 10) && (cellDl->currCfi == 1))) + { + /* Use CFI 2 in this case */ + iTbs = (ueDl->laCb[cwIdx].deltaiTbs + + ((*(RgSchCmnCqiToTbs *)(cellDl->cqiToTbsTbl[0][2]))[cqi])* 100)/100; + + RG_SCH_CHK_ITBS_RANGE(iTbs, RGSCH_NUM_ITBS - 1); + } + else + { + iTbs = ueDl->mimoInfo.cwInfo[cwIdx].iTbs[noLyr - 1]; + } + iTbs = RGSCH_MIN(iTbs, cell->thresholds.maxDlItbs); + } + else /* CFI Changed. Update with new iTbs Reset the BLER*/ +#endif + { + S32 tmpiTbs = (*(RgSchCmnCqiToTbs *)(cellDl->cqiToTbsTbl[0][cfi]))[cqi]; + + iTbs = (ueDl->laCb[cwIdx].deltaiTbs + tmpiTbs*100)/100; + + RG_SCH_CHK_ITBS_RANGE(iTbs, tmpiTbs); + + iTbs = RGSCH_MIN(iTbs, cell->thresholds.maxDlItbs); + + ueDl->mimoInfo.cwInfo[cwIdx].iTbs[noLyr - 1] = iTbs; + + ueDl->lastCfi = cfi; + ueDl->laCb[cwIdx].deltaiTbs = 0; + } + + RETVALUE(iTbs); +} + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 1/2/6/7. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRb1Tb1Cw + * Purpose: Allocate TB1 on CW1. + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRbTM1/2/6/7 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRb1Tb1Cw +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + S16 ret; + U8 numRb; + TRC2(rgSCHCmnDlAllocTxRb1Tb1Cw); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); +#ifdef RG_5GTF + if (ue->ue5gtfCb.rank == 2) + { + allocInfo->dciFormat = TFU_DCI_FORMAT_B2; + } + else + { + allocInfo->dciFormat = TFU_DCI_FORMAT_B1; + } +#else + allocInfo->dciFormat = rgSCHCmnSlctPdcchFrmt(cell, ue, \ + allocInfo->raType); +#endif + ret = rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, &proc->tbInfo[0],\ + bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + /* Adding UE to RbAllocInfo TX Lst */ + rgSCHCmnDlRbInfoAddUeTx(cell, cellWdAllocInfo, ue, proc); + /* Fill UE alloc Info */ + allocInfo->rbsReq = numRb; + allocInfo->dlSf = subFrm; +#ifdef RG_5GTF + allocInfo->vrbgReq = numRb/MAX_5GTF_VRBG_SIZE; +#endif + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 1/2/6/7. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRb1Tb1Cw + * Purpose: Allocate TB1 on CW1. + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRbTM1/2/6/7 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRb1Tb1Cw +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + S16 ret; + U8 numRb; + TRC2(rgSCHCmnDlAllocRetxRb1Tb1Cw); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + +#ifndef RG_5GTF + /* 5GTF: RETX DCI format same as TX */ + allocInfo->dciFormat = rgSCHCmnSlctPdcchFrmt(cell, ue, \ + &allocInfo->raType); +#endif + + /* Get the Allocation in terms of RBs that are required for + * this retx of TB1 */ + ret = rgSCHCmnDlAlloc1CwRetxRb(cell, subFrm, ue, &proc->tbInfo[0], + 1, &numRb, effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + /* Fix : syed If TxRetx allocation failed then add the UE along with the proc + * to the nonSchdTxRetxUeLst and let spfc scheduler take care of it during + * finalization. */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + /* Fill UE alloc Info */ + allocInfo->rbsReq = numRb; + allocInfo->dlSf = subFrm; +#ifdef RG_5GTF + allocInfo->vrbgReq = numRb/MAX_5GTF_VRBG_SIZE; +#endif + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 2. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM1 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM1 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM1(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocTxRbTM1); + rgSCHCmnDlAllocTxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 2. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM1 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM1 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM1(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocRetxRbTM1); + rgSCHCmnDlAllocRetxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 2. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM2 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM2 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM2(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocTxRbTM2); + rgSCHCmnDlAllocTxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 2. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM2 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM2 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM2(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocRetxRbTM2); + rgSCHCmnDlAllocRetxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 3. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM3 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM3 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM3(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + + TRC2(rgSCHCmnDlAllocTxRbTM3); + + /* Both TBs free for TX allocation */ + rgSCHCmnDlTM3TxTx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 3. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM3 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM3 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM3(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + + TRC2(rgSCHCmnDlAllocRetxRbTM3); + + if ((proc->tbInfo[0].state == HQ_TB_NACKED) && + (proc->tbInfo[1].state == HQ_TB_NACKED)) + { +#ifdef LAA_DBG_LOG + printf ("RETX RB TM3 nack for both hqp %d cell %d \n", proc->procId, proc->hqE->cell->cellId); +#endif + /* Both TBs require RETX allocation */ + rgSCHCmnDlTM3RetxRetx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + } + else + { + /* One of the TBs need RETX allocation. Other TB may/maynot + * be available for new TX allocation. */ + rgSCHCmnDlTM3TxRetx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + } + + RETVOID; +} + + +/** + * @brief This function performs the DCI format selection in case of + * Transmit Diversity scheme where there can be more + * than 1 option for DCI format selection. + * + * @details + * + * Function: rgSCHCmnSlctPdcchFrmt + * Purpose: 1. If DLFS is enabled, then choose TM specific + * DCI format for Transmit diversity. All the + * TM Specific DCI Formats support Type0 and/or + * Type1 resource allocation scheme. DLFS + * supports only Type-0&1 Resource allocation. + * 2. If DLFS is not enabled, select a DCI format + * which is of smaller size. Since Non-DLFS + * scheduler supports all Resource allocation + * schemes, selection is based on efficiency. + * + * Invoked by: DL UE Allocation by Common Scheduler. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[out] U8 *raType + * @return TfuDciFormat + * + **/ +#ifdef ANSI +PUBLIC TfuDciFormat rgSCHCmnSlctPdcchFrmt +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 *raType +) +#else +PUBLIC TfuDciFormat rgSCHCmnSlctPdcchFrmt(cell, ue, raType) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 *raType; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHCmnSlctPdcchFrmt); + + /* ccpu00140894- Selective DCI Format and RA type should be selected only + * after TX Mode transition is completed*/ + if ((cellSch->dl.isDlFreqSel) && (ue->txModeTransCmplt)) + { + *raType = rgSchCmnDciFrmtOptns[ue->mimoInfo.txMode-1].spfcDciRAType; + RETVALUE(rgSchCmnDciFrmtOptns[ue->mimoInfo.txMode-1].spfcDciFrmt); + } + else + { + *raType = rgSchCmnDciFrmtOptns[ue->mimoInfo.txMode-1].prfrdDciRAType; + RETVALUE(rgSchCmnDciFrmtOptns[ue->mimoInfo.txMode-1].prfrdDciFrmt); + } +} + + +/** + * @brief This function handles Retx allocation in case of TM3 UEs + * where both the TBs were NACKED previously. + * + * @details + * + * Function: rgSCHCmnDlTM3RetxRetx + * Purpose: If forceTD flag enabled + * TD for TB1 on CW1. + * Else + * DCI Frmt 2A and RA Type 0 + * RI layered SM of both TBs on 2 CWs + * Add UE to cell Alloc Info. + * Fill UE alloc Info. + * + * + * Successful allocation is indicated by non-zero effBo value. + * + * Invoked by: rgSCHCmnDlAllocRbTM3 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM3RetxRetx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM3RetxRetx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + S16 ret; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + Bool swpFlg; + U8 precInfo; + U8 noTxLyrs; + U8 precInfoAntIdx; + + TRC2(rgSCHCmnDlTM3RetxRetx); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + swpFlg = FALSE; +/* Fix for ccpu00123927: Retransmit 2 codewords irrespective of current rank */ + { + allocInfo->dciFormat = TFU_DCI_FORMAT_2A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE0; + + ret = rgSCHCmnDlAlloc2CwRetxRb(cell, subFrm, ue, proc, &numRb, &swpFlg,\ + effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + /* Fix for ccpu00123927: Retransmit 2 codewords irrespective of current rank */ + noTxLyrs = proc->tbInfo[0].numLyrs + proc->tbInfo[1].numLyrs; +#ifdef FOUR_TX_ANTENNA + /*Chandra: For 4X4 MIM RETX with noTxLyrs=3, CW0 should be 1-LyrTB and CW1 should + * have 2-LyrTB as per Table 6.3.3.2-1 of 36.211 */ + if(noTxLyrs == 3 && proc->tbInfo[0].numLyrs==2) + { + swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; + } +#endif + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + precInfo = (getPrecInfoFunc[0][precInfoAntIdx])(cell, ue, noTxLyrs, TRUE); + } + +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to allocInfo RETX Lst */ + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + } + /* Fill UE alloc Info scratch pad */ + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, swpFlg, \ + precInfo, noTxLyrs, subFrm); + + RETVOID; +} + + +/** + * @brief This function handles Retx allocation in case of TM4 UEs + * where both the TBs were NACKED previously. + * + * @details + * + * Function: rgSCHCmnDlTM4RetxRetx + * Purpose: If forceTD flag enabled + * TD for TB1 on CW1. + * Else + * DCI Frmt 2 and RA Type 0 + * If RI == 1 + * 1 layer SM of TB1 on CW1. + * Else + * RI layered SM of both TBs on 2 CWs + * Add UE to cell Alloc Info. + * Fill UE alloc Info. + * + * + * Successful allocation is indicated by non-zero effBo value. + * + * Invoked by: rgSCHCmnDlAllocRbTM4 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM4RetxRetx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM4RetxRetx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + S16 ret; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + Bool swpFlg = FALSE; + U8 precInfo; +#ifdef FOUR_TX_ANTENNA + U8 precInfoAntIdx; +#endif + U8 noTxLyrs; + + TRC2(rgSCHCmnDlTM4RetxRetx); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + /* Irrespective of RI Schedule both CWs */ + allocInfo->dciFormat = TFU_DCI_FORMAT_2; + allocInfo->raType = RG_SCH_CMN_RA_TYPE0; + + ret = rgSCHCmnDlAlloc2CwRetxRb(cell, subFrm, ue, proc, &numRb, &swpFlg,\ + effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + noTxLyrs = proc->tbInfo[0].numLyrs + proc->tbInfo[1].numLyrs; + precInfo = 0; +#ifdef FOUR_TX_ANTENNA + /*Chandra: For 4X4 MIM RETX with noTxLyrs=3, CW0 should be 1-LyrTB and CW1 + * should have 2-LyrTB as per Table 6.3.3.2-1 of 36.211 */ + if(noTxLyrs == 3 && proc->tbInfo[0].numLyrs==2) + { + swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; +} +precInfoAntIdx = cell->numTxAntPorts/2 - 1; +precInfo = (getPrecInfoFunc[1][precInfoAntIdx])(cell, ue, noTxLyrs, TRUE); +#endif + +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to allocInfo RETX Lst */ + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + } + /* Fill UE alloc Info scratch pad */ + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, swpFlg, \ + precInfo, noTxLyrs, subFrm); + + RETVOID; +} + + + +/** + * @brief This function determines Transmission attributes + * incase of Spatial multiplexing for TX and RETX TBs. + * + * @details + * + * Function: rgSCHCmnDlSMGetAttrForTxRetx + * Purpose: 1. Reached here for a TM3/4 UE's HqP whose one of the TBs is + * NACKED and the other TB is either NACKED or WAITING. + * 2. Select the NACKED TB for RETX allocation. + * 3. Allocation preference for RETX TB by mapping it to a better + * CW (better in terms of efficiency). + * 4. Determine the state of the other TB. + * Determine if swapFlag were to be set. + * Swap flag would be set if Retx TB is cross + * mapped to a CW. + * 5. If UE has new data available for TX and if the other TB's state + * is ACKED then set furtherScope as TRUE. + * + * Invoked by: rgSCHCmnDlTM3[4]TxRetx + * + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchDlHqTbCb **retxTb + * @param[out] RgSchDlHqTbCb **txTb + * @param[out] Bool *frthrScp + * @param[out] Bool *swpFlg + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlSMGetAttrForTxRetx +( +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +RgSchDlHqTbCb **retxTb, +RgSchDlHqTbCb **txTb, +Bool *frthrScp, +Bool *swpFlg +) +#else +PRIVATE Void rgSCHCmnDlSMGetAttrForTxRetx(ue, proc, retxTb, txTb, frthrScp,\ + swpFlg) +RgSchUeCb *ue; +RgSchDlHqProcCb *proc; +RgSchDlHqTbCb **retxTb; +RgSchDlHqTbCb **txTb; +Bool *frthrScp; +Bool *swpFlg; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,proc->hqE->cell); + RgSchDlRbAlloc *allocInfo; + + TRC2(rgSCHCmnDlSMGetAttrForTxRetx); + + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + *retxTb = &proc->tbInfo[0]; + *txTb = &proc->tbInfo[1]; + /* TENB_BRDCM_TM4- Currently disabling swapflag for TM3/TM4, since + * HqFeedback processing does not consider a swapped hq feedback */ + if ((ue->mimoInfo.txMode == RGR_UE_TM_4) && (ueDl->mimoInfo.btrCwIdx == 1)) + { + *swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; + } + if (proc->tbInfo[1].state == HQ_TB_ACKED) + { + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, proc->hqE->cell); + *frthrScp = allocInfo->mimoAllocInfo.hasNewTxData; + } + } + else + { + *retxTb = &proc->tbInfo[1]; + *txTb = &proc->tbInfo[0]; + /* TENB_BRDCM_TM4 - Currently disabling swapflag for TM3/TM4, since + * HqFeedback processing does not consider a swapped hq feedback */ + if ((ue->mimoInfo.txMode == RGR_UE_TM_4) && (ueDl->mimoInfo.btrCwIdx == 0)) + { + *swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; + } + if (proc->tbInfo[0].state == HQ_TB_ACKED) + { + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, proc->hqE->cell); + *frthrScp = allocInfo->mimoAllocInfo.hasNewTxData; + } + } + RETVOID; +} + + +/** + * @brief Determine Precoding information for TM3 2 TX Antenna. + * + * @details + * + * Function: rgSCHCmnDlTM3PrecInf2 + * Purpose: + * + * Invoked by: rgSCHCmnDlGetAttrForTM3 + * + * @param[in] RgSchUeCb *ue + * @param[in] U8 numTxLyrs + * @param[in] Bool bothCwEnbld + * @return U8 + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnDlTM3PrecInf2 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +) +#else +PRIVATE U8 rgSCHCmnDlTM3PrecInf2(ue, numTxLyrs, bothCwEnbld) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 numTxLyrs; +Bool bothCwEnbld; +#endif +{ + TRC2(rgSCHCmnDlTM3PrecInf2); + + RETVALUE(0); +} + + +/** + * @brief Determine Precoding information for TM4 2 TX Antenna. + * + * @details + * + * Function: rgSCHCmnDlTM4PrecInf2 + * Purpose: To determine a logic of deriving precoding index + * information from 36.212 table 5.3.3.1.5-4 + * + * Invoked by: rgSCHCmnDlGetAttrForTM4 + * + * @param[in] RgSchUeCb *ue + * @param[in] U8 numTxLyrs + * @param[in] Bool bothCwEnbld + * @return U8 + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnDlTM4PrecInf2 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +) +#else +PRIVATE U8 rgSCHCmnDlTM4PrecInf2(ue, numTxLyrs, bothCwEnbld) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 numTxLyrs; +Bool bothCwEnbld; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 precIdx; + + TRC2(rgSCHCmnDlTM4PrecInf2); + + if (ueDl->mimoInfo.ri == numTxLyrs) + { + if (ueDl->mimoInfo.ri == 2) + { + /* PrecInfo corresponding to 2 CW + Transmission */ + if (ue->mimoInfo.puschFdbkVld) + { + precIdx = 2; + } + else + { + precIdx = ueDl->mimoInfo.pmi - 1; + } + } + else + { + /* PrecInfo corresponding to 1 CW + * Transmission */ + if (ue->mimoInfo.puschFdbkVld) + { + precIdx = 5; + } + else + { + precIdx = ueDl->mimoInfo.pmi + 1; + } + } + } + else if (ueDl->mimoInfo.ri > numTxLyrs) + { + /* In case of choosing among the columns of a + * precoding matrix, choose the column corresponding + * to the MAX-CQI */ + if (ue->mimoInfo.puschFdbkVld) + { + precIdx = 5; + } + else + { + precIdx = (ueDl->mimoInfo.pmi- 1)* 2 + 1; + } + } + else /* if RI < numTxLyrs */ + { + precIdx = (ueDl->mimoInfo.pmi < 2)? 0:1; + } + RETVALUE(precIdx); +} + + +/** + * @brief Determine Precoding information for TM3 4 TX Antenna. + * + * @details + * + * Function: rgSCHCmnDlTM3PrecInf4 + * Purpose: To determine a logic of deriving precoding index + * information from 36.212 table 5.3.3.1.5A-2 + * + * Invoked by: rgSCHCmnDlGetAttrForTM3 + * + * @param[in] RgSchUeCb *ue + * @param[in] U8 numTxLyrs + * @param[in] Bool bothCwEnbld + * @return U8 + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnDlTM3PrecInf4 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +) +#else +PRIVATE U8 rgSCHCmnDlTM3PrecInf4(ue, numTxLyrs, bothCwEnbld) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 numTxLyrs; +Bool bothCwEnbld; +#endif +{ + U8 precIdx; + + TRC2(rgSCHCmnDlTM3PrecInf4); + + if (bothCwEnbld) + { + precIdx = numTxLyrs - 2; + } + else /* one 1 CW transmission */ + { + precIdx = 1; + } + RETVALUE(precIdx); +} + + +/** + * @brief Determine Precoding information for TM4 4 TX Antenna. + * + * @details + * + * Function: rgSCHCmnDlTM4PrecInf4 + * Purpose: To determine a logic of deriving precoding index + * information from 36.212 table 5.3.3.1.5-5 + * + * Invoked by: rgSCHCmnDlGetAttrForTM4 + * + * @param[in] RgSchUeCb *ue + * @param[in] U8 numTxLyrs + * @param[in] Bool bothCwEnbld + * @return U8 + * + **/ +#ifdef ANSI +PRIVATE U8 rgSCHCmnDlTM4PrecInf4 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 numTxLyrs, +Bool bothCwEnbld +) +#else +PRIVATE U8 rgSCHCmnDlTM4PrecInf4(cell, ue, numTxLyrs, bothCwEnbld) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 numTxLyrs; +Bool bothCwEnbld; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 precInfoBaseIdx, precIdx; + + TRC2(rgSCHCmnDlTM4PrecInf4); + + precInfoBaseIdx = (ue->mimoInfo.puschFdbkVld)? (16): + (ueDl->mimoInfo.pmi); + if (bothCwEnbld) + { + precIdx = precInfoBaseIdx + (numTxLyrs-2)*17; + } + else /* one 1 CW transmission */ + { + precInfoBaseIdx += 1; + precIdx = precInfoBaseIdx + (numTxLyrs-1)*17; + } + RETVALUE(precIdx); +} + + +/** + * @brief This function determines Transmission attributes + * incase of TM3 scheduling. + * + * @details + * + * Function: rgSCHCmnDlGetAttrForTM3 + * Purpose: Determine retx TB and tx TB based on TB states. + * If forceTD enabled + * perform only retx TB allocation. + * If retxTB == TB2 then DCI Frmt = 2A, RA Type = 0. + * Else DCI Frmt and RA Type based on cell->isDlfsEnbld + * If RI == 1 + * perform retxTB allocation on CW1. + * Else if RI > 1 + * Determine further Scope and Swap Flag attributes + * assuming a 2 CW transmission of RetxTB and new Tx TB. + * If no further scope for new TX allocation + * Allocate only retx TB using 2 layers if + * this TB was previously transmitted using 2 layers AND + * number of Tx antenna ports == 4. + * otherwise do single layer precoding. + * + * Invoked by: rgSCHCmnDlTM3TxRetx + * + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @param[out] U8 *numTxLyrs + * @param[out] Bool *isTraDiv + * @param[out] U8 *prcdngInf + * @param[out] U8 *raType + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlGetAttrForTM3 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U8 *numTxLyrs, +TfuDciFormat *dciFrmt, +U8 *prcdngInf, +RgSchDlHqTbCb **retxTb, +RgSchDlHqTbCb **txTb, +Bool *frthrScp, +Bool *swpFlg, +U8 *raType +) +#else +PRIVATE Void rgSCHCmnDlGetAttrForTM3(cell, ue, proc, numTxLyrs, dciFrmt,\ + prcdngInf, retxTb, txTb, frthrScp, swpFlg, raType) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlHqProcCb *proc; +U8 *numTxLyrs; +TfuDciFormat *dciFrmt; +U8 *prcdngInf; +RgSchDlHqTbCb **retxTb; +RgSchDlHqTbCb **txTb; +Bool *frthrScp; +Bool *swpFlg; +U8 *raType; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 precInfoAntIdx; + + TRC2(rgSCHCmnDlGetAttrForTM3); + + /* Avoiding Tx-Retx for LAA cell as firstSchedTime is associated with + HQP */ + /* Integration_fix: SPS Proc shall always have only one Cw */ +#ifdef LTEMAC_SPS + if (((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD)) +#ifdef LTE_ADV + ||(TRUE == rgSCHLaaSCellEnabled(cell)) +#endif + ) +#else + if ((ueDl->mimoInfo.forceTD) +#ifdef LTE_ADV + || (TRUE == rgSCHLaaSCellEnabled(cell)) +#endif + ) +#endif + { + /* Transmit Diversity. Format based on dlfsEnabled + * No further scope */ + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + *retxTb = &proc->tbInfo[0]; + *dciFrmt = rgSCHCmnSlctPdcchFrmt(cell, ue, raType); + } + else + { + *retxTb = &proc->tbInfo[1]; + *dciFrmt = TFU_DCI_FORMAT_2A; + *raType = RG_SCH_CMN_RA_TYPE0; + } + *numTxLyrs = 1; + *frthrScp = FALSE; + *prcdngInf = 0; + RETVOID; + } + + /* Determine the 2 TB transmission attributes */ + rgSCHCmnDlSMGetAttrForTxRetx(ue, proc, retxTb, txTb, \ + frthrScp, swpFlg); + if (*frthrScp) + { + /* Prefer allocation of RETX TB over 2 layers rather than combining + * it with a new TX. */ + if ((ueDl->mimoInfo.ri == 2) + && ((*retxTb)->numLyrs == 2) && (cell->numTxAntPorts == 4)) + { + /* Allocate TB on CW1, using 2 Lyrs, + * Format 2, precoding accordingly */ + *numTxLyrs = 2; + *frthrScp = FALSE; + } + else + { + *numTxLyrs= ((*retxTb)->numLyrs + ueDl->mimoInfo.cwInfo[!(ueDl->mimoInfo.btrCwIdx)].noLyr); + + if((*retxTb)->tbIdx == 0 && ((*retxTb)->numLyrs == 2 ) && *numTxLyrs ==3) + { + *swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; + } + else if((*retxTb)->tbIdx == 1 && ((*retxTb)->numLyrs == 1) && *numTxLyrs ==3) + { + *swpFlg = TRUE; + proc->cwSwpEnabled = TRUE; + } + } + + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + *prcdngInf = (getPrecInfoFunc[0][precInfoAntIdx])\ + (cell, ue, ueDl->mimoInfo.ri, *frthrScp); + *dciFrmt = TFU_DCI_FORMAT_2A; + *raType = RG_SCH_CMN_RA_TYPE0; + } + else /* frthrScp == FALSE */ + { + if (cell->numTxAntPorts == 2) + { + /* Transmit Diversity */ + *numTxLyrs = 1; + if ((*retxTb)->tbIdx == 0) + { + *dciFrmt = rgSCHCmnSlctPdcchFrmt(cell, ue, raType); + } + else + { + /* If retxTB is TB2 then use format 2A */ + *dciFrmt = TFU_DCI_FORMAT_2A; + *raType = RG_SCH_CMN_RA_TYPE0; + } + *prcdngInf = 0; + RETVOID; + } + else /* NumAntPorts == 4 */ + { + if ((*retxTb)->numLyrs == 2) + { + /* Allocate TB on CW1, using 2 Lyrs, + * Format 2A, precoding accordingly */ + *numTxLyrs = 2; + *dciFrmt = TFU_DCI_FORMAT_2A; + *raType = RG_SCH_CMN_RA_TYPE0; + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + *prcdngInf = (getPrecInfoFunc[0][precInfoAntIdx])(cell, ue, *numTxLyrs, *frthrScp); + RETVOID; + } + else + { + /* Transmit Diversity */ + *numTxLyrs = 1; + if ((*retxTb)->tbIdx == 0) + { + *dciFrmt = rgSCHCmnSlctPdcchFrmt(cell, ue, raType); + } + else + { + /* If retxTB is TB2 then use format 2A */ + *dciFrmt = TFU_DCI_FORMAT_2A; + *raType = RG_SCH_CMN_RA_TYPE0; + } + *prcdngInf = 0; + RETVOID; + } + } + } + + RETVOID; +} + + + +/** + * @brief This function determines Transmission attributes + * incase of TM4 scheduling. + * + * @details + * + * Function: rgSCHCmnDlGetAttrForTM4 + * Purpose: Determine retx TB and tx TB based on TB states. + * If forceTD enabled + * perform only retx TB allocation. + * If retxTB == TB2 then DCI Frmt = 2, RA Type = 0. + * Else DCI Frmt and RA Type based on cell->isDlfsEnbld + * If RI == 1 + * perform retxTB allocation on CW1. + * Else if RI > 1 + * Determine further Scope and Swap Flag attributes + * assuming a 2 CW transmission of RetxTB and new Tx TB. + * If no further scope for new TX allocation + * Allocate only retx TB using 2 layers if + * this TB was previously transmitted using 2 layers AND + * number of Tx antenna ports == 4. + * otherwise do single layer precoding. + * + * Invoked by: rgSCHCmnDlTM4TxRetx + * + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @param[out] U8 *numTxLyrs + * @param[out] Bool *isTraDiv + * @param[out] U8 *prcdngInf + * @param[out] U8 *raType + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlGetAttrForTM4 +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U8 *numTxLyrs, +TfuDciFormat *dciFrmt, +U8 *prcdngInf, +RgSchDlHqTbCb **retxTb, +RgSchDlHqTbCb **txTb, +Bool *frthrScp, +Bool *swpFlg, +U8 *raType +) +#else +PRIVATE Void rgSCHCmnDlGetAttrForTM4(cell, ue, proc, numTxLyrs, dciFrmt,\ + prcdngInf, retxTb, txTb, frthrScp, swpFlg, raType) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgSchDlHqProcCb *proc; +U8 *numTxLyrs; +TfuDciFormat *dciFrmt; +U8 *prcdngInf; +RgSchDlHqTbCb **retxTb; +RgSchDlHqTbCb **txTb; +Bool *frthrScp; +Bool *swpFlg; +U8 *raType; +#endif +{ + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + U8 precInfoAntIdx; + + TRC2(rgSCHCmnDlGetAttrForTM4); + + *frthrScp = FALSE; + /* Integration_fix: SPS Proc shall always have only one Cw */ +#ifdef LTEMAC_SPS + if (((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD)) +#ifdef LTE_ADV + ||(TRUE == rgSCHLaaSCellEnabled(cell)) +#endif + ) +#else + if ((ueDl->mimoInfo.forceTD) +#ifdef LTE_ADV + || (TRUE == rgSCHLaaSCellEnabled(cell)) +#endif + ) +#endif + { + /* Transmit Diversity. Format based on dlfsEnabled + * No further scope */ + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + *retxTb = &proc->tbInfo[0]; + *dciFrmt = rgSCHCmnSlctPdcchFrmt(cell, ue, raType); + } + else + { + *retxTb = &proc->tbInfo[1]; + *dciFrmt = TFU_DCI_FORMAT_2; + *raType = RG_SCH_CMN_RA_TYPE0; + } + *numTxLyrs = 1; + *frthrScp = FALSE; + *prcdngInf = 0; + RETVOID; + } + + if (ueDl->mimoInfo.ri == 1) + { + /* single layer precoding. Format 2. + * No further scope */ + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + *retxTb = &proc->tbInfo[0]; + } + else + { + *retxTb = &proc->tbInfo[1]; + } + *numTxLyrs = 1; + *dciFrmt = TFU_DCI_FORMAT_2; + *raType = RG_SCH_CMN_RA_TYPE0; + *frthrScp = FALSE; + *prcdngInf = 0; /*When RI= 1*/ + RETVOID; + } + + /* Determine the 2 TB transmission attributes */ + rgSCHCmnDlSMGetAttrForTxRetx(ue, proc, retxTb, txTb, \ + frthrScp, swpFlg); + *dciFrmt = TFU_DCI_FORMAT_2; + *raType = RG_SCH_CMN_RA_TYPE0; + if (*frthrScp) + { + /* Prefer allocation of RETX TB over 2 layers rather than combining + * it with a new TX. */ + if ((ueDl->mimoInfo.ri == 2) + && ((*retxTb)->numLyrs == 2) && (cell->numTxAntPorts == 4)) + { + /* Allocate TB on CW1, using 2 Lyrs, + * Format 2, precoding accordingly */ + *numTxLyrs = 2; + *frthrScp = FALSE; + } + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + *prcdngInf = (getPrecInfoFunc[1][precInfoAntIdx]) + (cell, ue, ueDl->mimoInfo.ri, *frthrScp); + } + else /* frthrScp == FALSE */ + { + if (cell->numTxAntPorts == 2) + { + /* single layer precoding. Format 2. */ + *numTxLyrs = 1; + *prcdngInf = (getPrecInfoFunc[1][cell->numTxAntPorts/2 - 1])\ + (cell, ue, *numTxLyrs, *frthrScp); + RETVOID; + } + else /* NumAntPorts == 4 */ + { + if ((*retxTb)->numLyrs == 2) + { + /* Allocate TB on CW1, using 2 Lyrs, + * Format 2, precoding accordingly */ + *numTxLyrs = 2; + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + *prcdngInf = (getPrecInfoFunc[1][precInfoAntIdx])\ + (cell, ue, *numTxLyrs, *frthrScp); + RETVOID; + } + else + { + /* Allocate TB with 1 lyr precoding, + * Format 2, precoding info accordingly */ + *numTxLyrs = 1; + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + *prcdngInf = (getPrecInfoFunc[1][precInfoAntIdx])\ + (cell, ue, *numTxLyrs, *frthrScp); + RETVOID; + } + } + } + + RETVOID; +} + + +/** + * @brief This function handles Retx allocation in case of TM3 UEs + * where previously one of the TBs was NACKED and the other + * TB is either ACKED/WAITING. + * + * @details + * + * Function: rgSCHCmnDlTM3TxRetx + * Purpose: Determine the TX attributes for TM3 TxRetx Allocation. + * If futher Scope for New Tx Allocation on other TB + * Perform RETX alloc'n on 1 CW and TX alloc'n on other. + * Add UE to cell wide RetxTx List. + * Else + * Perform only RETX alloc'n on CW1. + * Add UE to cell wide Retx List. + * + * effBo is set to a non-zero value if allocation is + * successful. + * + * Invoked by: rgSCHCmnDlAllocRbTM3 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM3TxRetx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM3TxRetx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + S16 ret; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + RgSchDlHqTbCb *retxTb, *txTb; + Bool frthrScp; + Bool swpFlg; + U8 prcdngInf; + U8 numTxLyrs; + + TRC2(rgSCHCmnDlTM3TxRetx); + frthrScp = FALSE; + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + swpFlg = FALSE; + + /* Determine the transmission attributes */ + rgSCHCmnDlGetAttrForTM3(cell, ue, proc, &numTxLyrs, &allocInfo->dciFormat,\ + &prcdngInf, &retxTb, &txTb, &frthrScp, &swpFlg,\ + &allocInfo->raType); + + if (frthrScp) + { +#ifdef LAA_DBG_LOG + printf ("TX RETX called from proc %d cell %d \n",proc->procId, cell->cellId); +#endif + ret = rgSCHCmnDlAlloc2CwTxRetxRb(cell, subFrm, ue, retxTb, txTb,\ + &numRb, effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + /* Adding UE to RbAllocInfo RETX-TX Lst */ + rgSCHCmnDlRbInfoAddUeRetxTx(cell, cellWdAllocInfo, ue, proc); + } + else + { + ret = rgSCHCmnDlAlloc1CwRetxRb(cell, subFrm, ue, retxTb, + numTxLyrs, &numRb, effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to allocInfo RETX Lst */ + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + } + } + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, swpFlg, \ + prcdngInf, numTxLyrs, subFrm); + + RETVOID; +} + + +/** + * @brief This function handles Retx allocation in case of TM4 UEs + * where previously one of the TBs was NACKED and the other + * TB is either ACKED/WAITING. + * + * @details + * + * Function: rgSCHCmnDlTM4TxRetx + * Purpose: Determine the TX attributes for TM4 TxRetx Allocation. + * If futher Scope for New Tx Allocation on other TB + * Perform RETX alloc'n on 1 CW and TX alloc'n on other. + * Add UE to cell wide RetxTx List. + * Else + * Perform only RETX alloc'n on CW1. + * Add UE to cell wide Retx List. + * + * effBo is set to a non-zero value if allocation is + * successful. + * + * Invoked by: rgSCHCmnDlAllocRbTM4 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM4TxRetx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM4TxRetx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + S16 ret; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + RgSchDlHqTbCb *retxTb, *txTb; + Bool frthrScp; + Bool swpFlg; + U8 prcdngInf; + U8 numTxLyrs; + + TRC2(rgSCHCmnDlTM4TxRetx); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + swpFlg = FALSE; + + /* Determine the transmission attributes */ + rgSCHCmnDlGetAttrForTM4(cell, ue, proc, &numTxLyrs, &allocInfo->dciFormat,\ + &prcdngInf, &retxTb, &txTb, &frthrScp, &swpFlg,\ + &allocInfo->raType); + + if (frthrScp) + { + ret = rgSCHCmnDlAlloc2CwTxRetxRb(cell, subFrm, ue, retxTb, txTb,\ + &numRb, effBo); + if (ret == RFAILED) + { + /* Fix : syed If TxRetx allocation failed then add the UE along + * with the proc to the nonSchdTxRetxUeLst and let spfc scheduler + * take care of it during finalization. */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + /* Adding UE to RbAllocInfo RETX-TX Lst */ + rgSCHCmnDlRbInfoAddUeRetxTx(cell, cellWdAllocInfo, ue, proc); + } + else + { + ret = rgSCHCmnDlAlloc1CwRetxRb(cell, subFrm, ue, retxTb, + numTxLyrs, &numRb, effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to allocInfo RETX Lst */ + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + } + } + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, swpFlg, \ + prcdngInf, numTxLyrs, subFrm) + + RETVOID; +} + + +/** + * @brief This function handles Retx allocation in case of TM4 UEs + * where previously both the TBs were ACKED and ACKED + * respectively. + * + * @details + * + * Function: rgSCHCmnDlTM3TxTx + * Purpose: Reached here for a TM3 UE's HqP's fresh allocation + * where both the TBs are free for TX scheduling. + * If forceTD flag is set + * perform TD on CW1 with TB1. + * precInfo = 0 + * else + * DCI Format = 2A. + * RA Type = Type0. + * RI layered precoding 2 TB on 2 CW. + * Set precoding info. + * Add UE to cellAllocInfo. + * Fill ueAllocInfo. + * + * effBo is set to a non-zero value if allocation is + * successful. + * + * Invoked by: rgSCHCmnDlAllocRbTM3 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM3TxTx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM3TxTx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchCmnDlUe *ueDl; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + U8 noTxLyrs; + U8 precInfo; + S16 ret; + U8 precInfoAntIdx; + + TRC2(rgSCHCmnDlTM3TxTx); + + ret = ROK; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + /* Integration_fix: SPS Proc shall always have only one Cw */ +#ifdef LTEMAC_SPS +#ifdef FOUR_TX_ANTENNA + if ((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD) || proc->hasDcch) /*Chandra Avoid DCCH to be SM */ +#else + if ((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD)) +#endif +#else + if (ueDl->mimoInfo.forceTD) /* Transmit Diversity (TD) */ +#endif + { + allocInfo->dciFormat = rgSCHCmnSlctPdcchFrmt(cell, ue, \ + &allocInfo->raType); + ret = rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, &proc->tbInfo[0],\ + bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + noTxLyrs = 1; + precInfo = 0; /* TD */ + } + else /* Precoding */ + { + allocInfo->dciFormat = TFU_DCI_FORMAT_2A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE0; + + /* Spatial Multiplexing using 2 CWs */ + ret = rgSCHCmnDlAlloc2CwTxRb(cell, subFrm, ue, proc, bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + noTxLyrs = ueDl->mimoInfo.ri; + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, getPrecInfoFunc[0], precInfoAntIdx); + precInfo = (getPrecInfoFunc[0][precInfoAntIdx])(cell, ue, noTxLyrs, TRUE); + } + +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to RbAllocInfo TX Lst */ + rgSCHCmnDlRbInfoAddUeTx(cell, cellWdAllocInfo, ue, proc); + } + /* Fill UE allocInfo scrath pad */ + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, FALSE, \ + precInfo, noTxLyrs, subFrm); + + RETVOID; +} + + +/** + * @brief This function handles Retx allocation in case of TM4 UEs + * where previously both the TBs were ACKED and ACKED + * respectively. + * + * @details + * + * Function: rgSCHCmnDlTM4TxTx + * Purpose: Reached here for a TM4 UE's HqP's fresh allocation + * where both the TBs are free for TX scheduling. + * If forceTD flag is set + * perform TD on CW1 with TB1. + * precInfo = 0 + * else + * DCI Format = 2. + * RA Type = Type0. + * If Rank == 1 + * Single layer precoding of TB1 on CW1. + * Set precoding info. + * else + * RI layered precoding 2 TB on 2 CW. + * Set precoding info. + * Add UE to cellAllocInfo. + * Fill ueAllocInfo. + * + * effBo is set to a non-zero value if allocation is + * successful. + * + * Invoked by: rgSCHCmnDlAllocRbTM4 + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlTM4TxTx +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlTM4TxTx(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchCmnDlUe *ueDl; + RgSchDlRbAlloc *allocInfo; + U8 numRb; + U8 precInfo; + U8 noTxLyrs; + U8 precInfoAntIdx; + S16 ret; + + TRC2(rgSCHCmnDlTM4TxTx); + + ret = ROK; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + /* Integration_fix: SPS Proc shall always have only one Cw */ +#ifdef LTEMAC_SPS +#ifdef FOUR_TX_ANTENNA + if ((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD) || proc->hasDcch) /*Chandra Avoid DCCH to be SM */ +#else + if ((RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) || + (ueDl->mimoInfo.forceTD)) +#endif +#else + if (ueDl->mimoInfo.forceTD) /* Transmit Diversity (TD) */ +#endif + { + allocInfo->dciFormat = rgSCHCmnSlctPdcchFrmt(cell, ue, \ + &allocInfo->raType); + + ret = rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, &proc->tbInfo[0],\ + bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + noTxLyrs = 1; + precInfo = 0; /* TD */ + } + else /* Precoding */ + { + allocInfo->dciFormat = TFU_DCI_FORMAT_2; + allocInfo->raType = RG_SCH_CMN_RA_TYPE0; + + if (ueDl->mimoInfo.ri == 1) + { + /* Single Layer SM using FORMAT 2 */ + ret = rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, &proc->tbInfo[0],\ + bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + noTxLyrs = 1; + precInfo = 0; /* PrecInfo as 0 for RI=1*/ + } + else + { + /* Spatial Multiplexing using 2 CWs */ + ret = rgSCHCmnDlAlloc2CwTxRb(cell, subFrm, ue, proc, bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + noTxLyrs = ueDl->mimoInfo.ri; + precInfoAntIdx = cell->numTxAntPorts/2 - 1; + precInfo = (getPrecInfoFunc[1][precInfoAntIdx])(cell, ue, noTxLyrs, TRUE); + } + } + + +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to RbAllocInfo TX Lst */ + rgSCHCmnDlRbInfoAddUeTx(cell, cellWdAllocInfo, ue, proc); + } + + /* Fill UE allocInfo scrath pad */ + RG_SCH_CMN_FILL_DL_TXINFO(allocInfo, numRb, FALSE, \ + precInfo, noTxLyrs, subFrm); + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 4. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM4 + * Purpose: Invokes the functionality particular to the + * current state of the TBs of the "proc". + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM4 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM4(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocTxRbTM4); + + /* Both TBs free for TX allocation */ + rgSCHCmnDlTM4TxTx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 4. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM4 + * Purpose: Invokes the functionality particular to the + * current state of the TBs of the "proc". + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM4 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM4(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocRetxRbTM4); + + if ((proc->tbInfo[0].state == HQ_TB_NACKED) && + (proc->tbInfo[1].state == HQ_TB_NACKED)) + { + /* Both TBs require RETX allocation */ + rgSCHCmnDlTM4RetxRetx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + } + else + { + /* One of the TBs need RETX allocation. Other TB may/maynot + * be available for new TX allocation. */ + rgSCHCmnDlTM4TxRetx(cell, subFrm, ue, bo, effBo,\ + proc, cellWdAllocInfo); + } + + RETVOID; +} + +#ifdef RG_UNUSED + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 5. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM5 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM5 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM5(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocTxRbTM5); +#if (ERRCLASS & ERRCLS_DEBUG) + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Invalid TM 5 for CRNTI:%d",ue->ueId); +#endif + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 5. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM5 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM5 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM5(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocRetxRbTM5); +#if (ERRCLASS & ERRCLS_DEBUG) + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Invalid TM 5 for CRNTI:%d",ue->ueId); +#endif + RETVOID; +} +#endif + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 6. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM6 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM6 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM6(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *ueDl; + S16 ret; + U8 numRb; + + TRC2(rgSCHCmnDlAllocTxRbTM6); + + ret = ROK; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + if (ueDl->mimoInfo.forceTD) + { + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + } + else + { + allocInfo->dciFormat = TFU_DCI_FORMAT_1B; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + /* Fill precoding information for FORMAT 1B */ + /* First 4 least significant bits to indicate PMI. + * 4th most significant corresponds to pmi Confirmation. + */ + allocInfo->mimoAllocInfo.precIdxInfo |= ue->mimoInfo.puschFdbkVld << 4; + allocInfo->mimoAllocInfo.precIdxInfo |= ueDl->mimoInfo.pmi; + } + ret = rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, &proc->tbInfo[0],\ + bo, &numRb, effBo); + if (ret == RFAILED) + { + /* If allocation couldn't be made then return */ + RETVOID; + } + +#ifdef LTEMAC_SPS + if (!RG_SCH_CMN_SPS_DL_IS_SPS_HQP(proc)) +#endif + { + /* Adding UE to RbAllocInfo TX Lst */ + rgSCHCmnDlRbInfoAddUeTx(cell, cellWdAllocInfo, ue, proc); + } + /* Fill UE alloc Info */ + allocInfo->rbsReq = numRb; + allocInfo->dlSf = subFrm; + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 6. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM6 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM6 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM6(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + RgSchCmnDlUe *ueDl; + S16 ret; + U8 numRb; + + TRC2(rgSCHCmnDlAllocRetxRbTM6); + + ret = ROK; + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + if (ueDl->mimoInfo.forceTD) + { + allocInfo->dciFormat = TFU_DCI_FORMAT_1A; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + } + else + { + allocInfo->dciFormat = TFU_DCI_FORMAT_1B; + allocInfo->raType = RG_SCH_CMN_RA_TYPE2; + /* Fill precoding information for FORMAT 1B */ + /* First 4 least significant bits to indicate PMI. + * 4th most significant corresponds to pmi Confirmation. + */ + allocInfo->mimoAllocInfo.precIdxInfo |= ue->mimoInfo.puschFdbkVld << 4; + allocInfo->mimoAllocInfo.precIdxInfo |= ueDl->mimoInfo.pmi; + } + + /* Get the Allocation in terms of RBs that are required for + * this retx of TB1 */ + ret = rgSCHCmnDlAlloc1CwRetxRb(cell, subFrm, ue, &proc->tbInfo[0], + 1, &numRb, effBo); + if (ret == RFAILED) + { + /* Allocation couldn't be made for Retx */ + rgSCHCmnDlAdd2NonSchdRetxLst(cellWdAllocInfo, ue, proc); + RETVOID; + } + /* Adding UE to allocInfo RETX Lst */ + rgSCHCmnDlRbInfoAddUeRetx(cell, cellWdAllocInfo, ue, proc); + /* Fill UE alloc Info */ + allocInfo->rbsReq = numRb; + allocInfo->dlSf = subFrm; + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * transmission for UEs configured with TM 7. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRbTM7 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocTxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocTxRbTM7 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocTxRbTM7(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocTxRbTM7); + rgSCHCmnDlAllocTxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * retransmission for UEs configured with TM 7. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRbTM7 + * Purpose: + * + * Reference Parameter effBo is filled with alloced bytes. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlAllocRetxRbTM7 +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PRIVATE Void rgSCHCmnDlAllocRetxRbTM7(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + TRC2(rgSCHCmnDlAllocRetxRbTM7); + rgSCHCmnDlAllocRetxRb1Tb1Cw(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo); + RETVOID; +} + + +/** + * @brief This function invokes the TM specific DL TX RB Allocation routine. + * + * @details + * + * Function: rgSCHCmnDlAllocTxRb + * Purpose: This function invokes the TM specific + * DL TX RB Allocation routine. + * + * Invoked by: Specific Schedulers + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return S16 + * + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnDlAllocTxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PUBLIC S16 rgSCHCmnDlAllocTxRb(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + U32 newSchBits = 0; + U32 prevSchBits = 0; + RgSchDlRbAlloc *allocInfo; + + TRC2(rgSCHCmnDlAllocTxRb); + + if ( !RGSCH_TIMEINFO_SAME((cell->crntTime),(ue->dl.lstSchTime) )) + { + ue->dl.aggTbBits = 0; + } + *effBo = 0; + + /* Calculate totals bits previously allocated */ + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + if (allocInfo->tbInfo[0].schdlngForTb) + { + prevSchBits += allocInfo->tbInfo[0].bytesReq; + } + if (allocInfo->tbInfo[1].schdlngForTb) + { + prevSchBits += allocInfo->tbInfo[1].bytesReq; + } + + /* Call TM specific RB allocation routine */ + (dlAllocTxRbFunc[ue->mimoInfo.txMode - 1])(cell, subFrm, ue, bo, effBo, \ + proc, cellWdAllocInfo); + + if (*effBo) + { + /* Calculate totals bits newly allocated */ + if (allocInfo->tbInfo[0].schdlngForTb) + { + newSchBits += allocInfo->tbInfo[0].bytesReq; + } + if (allocInfo->tbInfo[1].schdlngForTb) + { + newSchBits += allocInfo->tbInfo[1].bytesReq; + } + if (newSchBits > prevSchBits) + { + ue->dl.aggTbBits += ((newSchBits - prevSchBits) * 8); + RGSCHCPYTIMEINFO((cell->crntTime),(ue->dl.lstSchTime)) + } + } + + RETVALUE(ROK); +} + +/* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD +/** + * @brief Retransmit decision for TDD. Retx is avoided in below cases + * 1) DL Sf -> Spl Sf + * 2) DL SF -> DL SF 0 + * + * @details + * + * Function: rgSCHCmnRetxAvoidTdd + * Purpose: Avoid allocating RETX for cases 1, 2 + * + * Invoked by: rgSCHCmnRetxAvoidTdd + * + * @param[in] RgSchDlSf *curSf + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlHqProcCb *proc + * @return Bool + * + **/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnRetxAvoidTdd +( +RgSchDlSf *curSf, +RgSchCellCb *cell, +RgSchDlHqProcCb *proc +) +#else +PUBLIC Bool rgSCHCmnRetxAvoidTdd(curSf, cell, proc) +RgSchDlSf *curSf; +RgSchCellCb *cell; +RgSchDlHqProcCb *proc; +#endif +{ + RgSchTddSfType txSfType = 0; + + TRC2(rgSCHCmnRetxAvoidTdd); + + /* Get the RBs of TB that will be retransmitted */ + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + txSfType = proc->tbInfo[0].sfType; + +#ifdef XEON_SPECIFIC_CHANGES +#ifndef XEON_TDD_SPCL + /* Avoid re-transmission on Normal SF when the corresponding TB wss transmitted on SPCL SF */ + if(txSfType <= RG_SCH_SPL_SF_DATA && curSf->sfType >= RG_SCH_DL_SF_0) + { + RETVALUE(TRUE); + } +#endif +#endif + } + if (proc->tbInfo[1].state == HQ_TB_NACKED) + { + /* Select the TxSf with the highest num of possible REs + * In ascending order -> 1) SPL SF 2) DL_SF_0 3) DL_SF */ + txSfType = RGSCH_MAX(txSfType, proc->tbInfo[1].sfType); + +#ifdef XEON_SPECIFIC_CHANGES +#ifndef XEON_TDD_SPCL + /* Avoid re-transmission on Normal SF when the corresponding TB wss tranmitted on SPCL SF */ + if(txSfType <= RG_SCH_SPL_SF_DATA && curSf->sfType >= RG_SCH_DL_SF_0) + { + RETVALUE(TRUE); + } +#endif +#endif + } + + if (txSfType > curSf->sfType) + { + /* Avoid retx */ + RETVALUE(TRUE); + } + + /* Allow Retx */ + RETVALUE(FALSE); +} + +#else +/* DwPTS Scheduling Changes End */ + +/** + * @brief Avoid allocating RETX incase of collision + * with reserved resources for BCH/PSS/SSS occassions. + * + * @details + * + * Function: rgSCHCmnRetxAllocAvoid + * Purpose: Avoid allocating RETX incase of collision + * with reserved resources for BCH/PSS/SSS occassions + * + * Invoked by: rgSCHCmnDlAllocRetxRb + * + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @return Bool + * + **/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnRetxAllocAvoid +( +RgSchDlSf *subFrm, +RgSchCellCb *cell, +RgSchDlHqProcCb *proc +) +#else +PUBLIC Bool rgSCHCmnRetxAllocAvoid(subFrm, cell, proc) +RgSchDlSf *subFrm; +RgSchCellCb *cell; +RgSchDlHqProcCb *proc; +#endif +{ + U8 reqRbs; + + TRC2(rgSCHCmnRetxAllocAvoid); + + if (proc->tbInfo[0].state == HQ_TB_NACKED) + { + reqRbs = proc->tbInfo[0].dlGrnt.numRb; + } + else + { + reqRbs = proc->tbInfo[1].dlGrnt.numRb; + } + /* Consider the dlGrnt.numRb of the Retransmitting proc->tbInfo + * and current available RBs to determine if this RETX TB + * will collide with the BCH/PSS/SSS occassion */ + if (subFrm->sfNum % 5 == 0) + { + if ((subFrm->bwAssigned < cell->pbchRbEnd) && + (((subFrm->bwAssigned + reqRbs) - cell->pbchRbStart) > 0)) + { + RETVALUE(TRUE); + } + } + RETVALUE(FALSE); +} + +#endif + + +/** + * @brief This function invokes the TM specific DL RETX RB Allocation routine. + * + * @details + * + * Function: rgSCHCmnDlAllocRetxRb + * Purpose: This function invokes the TM specific + * DL RETX RB Allocation routine. + * + * Invoked by: Specific Schedulers + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] U32 bo + * @param[out] U32 *effBo + * @param[in] RgSchDlHqProcCb *proc + * @param[out] RgSchCmnDlRbAllocInfo *cellWdAllocInfo + * @return S16 + * + **/ +#ifdef ANSI +PUBLIC S16 rgSCHCmnDlAllocRetxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +U32 bo, +U32 *effBo, +RgSchDlHqProcCb *proc, +RgSchCmnDlRbAllocInfo *cellWdAllocInfo +) +#else +PUBLIC S16 rgSCHCmnDlAllocRetxRb(cell, subFrm, ue, bo, effBo, proc, cellWdAllocInfo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +U32 bo; +U32 *effBo; +RgSchDlHqProcCb *proc; +RgSchCmnDlRbAllocInfo *cellWdAllocInfo; +#endif +{ + U32 newSchBits = 0; + RgSchDlRbAlloc *allocInfo; + + TRC2(rgSCHCmnDlAllocRetxRb); + + if ( !RGSCH_TIMEINFO_SAME((cell->crntTime),(ue->dl.lstSchTime) )) + { + ue->dl.aggTbBits = 0; + } + + *effBo = 0; + /* Check for DL BW exhaustion */ + if (subFrm->bw <= subFrm->bwAssigned) + { + RETVALUE(RFAILED); + } + /* Call TM specific RB allocation routine */ + (dlAllocRetxRbFunc[ue->mimoInfo.txMode - 1])(cell, subFrm, ue, bo, effBo, \ + proc, cellWdAllocInfo); + + if (*effBo) + { + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + /* Calculate totals bits newly allocated */ + if (allocInfo->tbInfo[0].schdlngForTb) + { + newSchBits += allocInfo->tbInfo[0].bytesReq; + } + if (allocInfo->tbInfo[1].schdlngForTb) + { + newSchBits += allocInfo->tbInfo[1].bytesReq; + } + ue->dl.aggTbBits += (newSchBits * 8); + RGSCHCPYTIMEINFO((cell->crntTime),(ue->dl.lstSchTime)) + } + + RETVALUE(ROK); +} + + +/** + * @brief This function determines the RBs and Bytes required for + * Transmission on 1 CW. + * + * @details + * + * Function: rgSCHCmnDlAlloc1CwTxRb + * Purpose: This function determines the RBs and Bytes required + * for Transmission of DL SVC BO on 1 CW. + * Also, takes care of SVC by SVC allocation by tracking + * previous SVCs allocations. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: DL UE Allocation + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqTbCb *tbInfo + * @param[in] U32 bo + * @param[out] U8 *numRb + * @param[out] U32 *effBo + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlAlloc1CwTxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *tbInfo, +U32 bo, +U8 *numRb, +U32 *effBo +) +#else +PRIVATE S16 rgSCHCmnDlAlloc1CwTxRb(cell, subFrm, ue, tbInfo, bo, numRb, effBo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +RgSchDlHqTbCb *tbInfo; +U32 bo; +U8 *numRb; +U32 *effBo; +#endif +{ + U32 tbSz; + U8 imcs; + U8 iTbs; + RgSchCmnDlUe *ueDl; + RgSchDlRbAlloc *allocInfo; + U32 oldReq; + U32 reqBytes; + /* Correcting wrap around issue. + * This change has been done at mutliple places in this function.*/ + U32 tempNumRb; + TRC2(rgSCHCmnDlAlloc1CwTxRb); + + reqBytes = bo; + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + oldReq = ueDl->outStndAlloc; + +#ifdef RG_5GTF + //TODO_SID: Currently setting max Tb size wrt to 5GTF TM3 + iTbs = ue->ue5gtfCb.mcs; + ueDl->maxTbSz = MAX_5GTF_TB_SIZE * ue->ue5gtfCb.rank; + ueDl->maxRb = MAX_5GTF_PRBS; +#endif + ueDl->outStndAlloc += bo; + /* consider Cumulative amount of this BO and bytes so far allocated */ + bo = RGSCH_MIN(ueDl->outStndAlloc, ueDl->maxTbSz/8); + /* Get the number of REs needed for this bo. */ + //noRes = ((bo * 8 * 1024) / eff); + + /* Get the number of RBs needed for this transmission */ + /* Number of RBs = No of REs / No of REs per RB */ + //tempNumRb = RGSCH_CEIL(noRes, cellDl->noResPerRb[cfi]); + tempNumRb = MAX_5GTF_PRBS; + tbSz = RGSCH_MIN(bo, (rgSch5gtfTbSzTbl[iTbs]/8) * ue->ue5gtfCb.rank); + + /* DwPts Scheduling Changes End */ + *effBo = RGSCH_MIN(tbSz - oldReq, reqBytes); + +#ifdef RG_5GTF + //RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, imcs); + imcs = iTbs; +#endif + + + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[0], tbSz, \ + iTbs, imcs, tbInfo, ue->ue5gtfCb.rank); + *numRb = (U8) tempNumRb; + + /* Update the subframe Allocated BW field */ + subFrm->bwAssigned = subFrm->bwAssigned + tempNumRb - allocInfo->rbsReq; + + RETVALUE(ROK); +} + + +/** + * @brief This function is invoked in the event of any TB's allocation + * being underutilized by the specific scheduler. Here we reduce iMcs + * to increase redundancy and hence increase reception quality at UE. + * + * @details + * + * Function: rgSCHCmnRdcImcsTxTb + * Purpose: This function shall reduce the iMcs in accordance with + * the total consumed bytes by the UE at allocation + * finalization. + * + * Invoked by: UE DL Allocation finalization routine + * of specific scheduler. + * + * @param[in] RgSchDlRbAlloc *allocInfo + * @param[in] U8 tbInfoIdx + * @param[in] U32 cnsmdBytes + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnRdcImcsTxTb +( +RgSchDlRbAlloc *allocInfo, +U8 tbInfoIdx, +U32 cnsmdBytes +) +#else +PUBLIC Void rgSCHCmnRdcImcsTxTb(allocInfo, tbInfoIdx, cnsmdBytes) +RgSchDlRbAlloc *allocInfo; +U8 tbInfoIdx; +U32 cnsmdBytes; +#endif +{ + RETVOID; + /*The below functionality is not needed.*/ + U8 noLyr; + U8 iTbs; + U16 numRb; + + TRC2(rgSCHCmnRdcImcsTxTb); + + iTbs = allocInfo->tbInfo[tbInfoIdx].iTbs; + noLyr = allocInfo->tbInfo[tbInfoIdx].noLyr; + numRb = allocInfo->rbsAlloc; + if ( numRb > 0) + { + if ((rgTbSzTbl[noLyr-1][iTbs][numRb-1]/8) == cnsmdBytes) + { + RETVOID; + } + } + /* Get iTbs as suitable for the consumed bytes */ + while((rgTbSzTbl[noLyr-1][iTbs][numRb-1]/8) > cnsmdBytes) + { + if (iTbs == 0) + { + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, allocInfo->tbInfo[tbInfoIdx].\ + tbCb->dlGrnt.iMcs); + RETVOID; + } + iTbs--; + } + iTbs++; + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, allocInfo->tbInfo[tbInfoIdx].tbCb->dlGrnt.iMcs); + + RETVOID; +} + + +/** + * @brief This function determines the RBs and Bytes required for + * Transmission on 2 CWs. + * + * @details + * + * Function: rgSCHCmnDlAlloc2CwTxRb + * Purpose: This function determines the RBs and Bytes required + * for Transmission of DL SVC BO on 2 CWs. + * Also, takes care of SVC by SVC allocation by tracking + * previous SVCs allocations. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: TM3 and TM4 DL UE Allocation + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @param[in] RgSchDlHqProcCb bo + * @param[out] U8 *numRb + * @param[out] U32 *effBo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U32 bo, +U8 *numRbRef, +U32 *effBo +) +#else +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRb(cell, subFrm, ue, proc, bo, numRbRef, effBo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +RgSchDlHqProcCb *proc; +U32 bo; +U8 *numRbRef; +U32 *effBo; +#endif +{ + U32 noRes; + U32 eff1, eff2; + U32 tb1Sz, tb2Sz; + U8 imcs1, imcs2; + U8 noLyr1, noLyr2; + U8 iTbs1, iTbs2; + RgSchCmnDlCell *cellDl; + RgSchCmnDlUe *ueDl; + RgSchDlRbAlloc *allocInfo; + U32 oldReq; + U32 reqBytes; + /* Fix: MUE_PERTTI_DL */ + U32 numRb; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + U8 cfi = cellSch->dl.currCfi; + S16 availBw; + U32 availBits = 0; +#ifdef LTE_ADV + U32 boTmp = bo; +#endif + + TRC2(rgSCHCmnDlAlloc2CwTxRb); + + reqBytes = bo; + cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + oldReq = ueDl->outStndAlloc; + + + if (ueDl->maxTbBits > ue->dl.aggTbBits) + { + availBits = ueDl->maxTbBits - ue->dl.aggTbBits; + } + /* check if we can further allocate to this UE */ + if ((ue->dl.aggTbBits >= ueDl->maxTbBits) || + (allocInfo->tbInfo[0].bytesReq >= ueDl->maxTbSz/8) || + (allocInfo->tbInfo[1].bytesReq >= ueDl->maxTbSz/8) || + (allocInfo->rbsReq >= ueDl->maxRb)) + { + RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId, + "rgSCHCmnDlAllocRb(): UEs max allocation exceed"); + RETVALUE(RFAILED); + } + + noLyr1 = ueDl->mimoInfo.cwInfo[0].noLyr; + noLyr2 = ueDl->mimoInfo.cwInfo[1].noLyr; + + /* If there is no CFI change, continue to use the BLER based + * iTBS value */ + if (ueDl->lastCfi == cfi) + { + iTbs1 = ueDl->mimoInfo.cwInfo[0].iTbs[noLyr1 - 1]; + iTbs2 = ueDl->mimoInfo.cwInfo[1].iTbs[noLyr2 - 1]; + } + else + { + U8 cqi = ueDl->mimoInfo.cwInfo[0].cqi; +#ifdef LTE_TDD + iTbs1 = (U8) rgSchCmnFetchItbs(cell, ueDl, subFrm, cqi, cfi, 0, noLyr1); +#else + iTbs1 = (U8) rgSchCmnFetchItbs(cell, ueDl, cqi, cfi, 0, noLyr1); +#endif + + cqi = ueDl->mimoInfo.cwInfo[1].cqi; +#ifdef LTE_TDD + iTbs2 = (U8) rgSchCmnFetchItbs(cell, ueDl, subFrm, cqi, cfi, 1, noLyr2); +#else + iTbs2 = (U8) rgSchCmnFetchItbs(cell, ueDl, cqi, cfi, 1, noLyr2); +#endif + } + + /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure + * issue for VoLTE call */ + //if ((proc->hasDcch) || (TRUE == rgSCHLaaSCellEnabled(cell))) + if (proc->hasDcch) + { + if (iTbs1 > 5) + { + iTbs1 = iTbs1 - 5; + } + else + { + iTbs1 = 0; + } + if (iTbs2 > 5) + { + iTbs2 = iTbs2 - 5; + } + else + { + iTbs2 = 0; + } + } + else if(!cellSch->dl.isDlFreqSel) + { +#ifdef LTE_TDD + /* for Tdd reduce iTbs only for SF0. SF5 contains only + * SSS and can be ignored */ + if (subFrm->sfNum == 0) + { + (iTbs1 > 1)? (iTbs1 -= 1) : (iTbs1 = 0); + (iTbs2 > 1)? (iTbs2 -= 1) : (iTbs2 = 0); + } + /* For SF 3 and 8 CRC is getting failed in DL. + Need to do proper fix after the replay from + BRCM PHY team*/ +#ifdef CA_PHY_BRDCM_61765 + if ((subFrm->sfNum == 3) || (subFrm->sfNum == 8)) + { + (iTbs1 > 2)? (iTbs1 -= 2) : (iTbs1 = 0); + (iTbs2 > 2)? (iTbs2 -= 2) : (iTbs2 = 0); + } +#endif +#else +#endif + } + +#ifdef LTE_TDD + if(subFrm->sfType == RG_SCH_SPL_SF_DATA) + { + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, cfi); + } +#endif + + eff1 = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[noLyr1 - 1][cfi]))[iTbs1]; + eff2 = (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[noLyr2 - 1][cfi]))[iTbs2]; + + + bo = RGSCH_MIN(bo,availBits/8); + ueDl->outStndAlloc += bo; + /* consider Cumulative amount of this BO and bytes so far allocated */ + bo = RGSCH_MIN(ueDl->outStndAlloc, ueDl->maxTbBits/8); + bo = RGSCH_MIN(RGSCH_MAX(RGSCH_CMN_MIN_GRNT_HDR, (bo*eff1)/(eff1+eff2)), + ueDl->maxTbSz/8) + + RGSCH_MIN(RGSCH_MAX(RGSCH_CMN_MIN_GRNT_HDR, (bo*eff2)/(eff1+eff2)), + (ueDl->maxTbSz)/8) + + 1; /* Add 1 to adjust the truncation at weighted averaging */ + /* Get the number of REs needed for this bo. */ + noRes = ((bo * 8 * 1024) / (eff1 + eff2)); + + /* Get the number of RBs needed for this transmission */ + /* Number of RBs = No of REs / No of REs per RB */ + numRb = RGSCH_CEIL(noRes, cellDl->noResPerRb[cfi]); + /* Cannot exceed the maximum number of RBs per UE */ + if (numRb > ueDl->maxRb) + { + numRb = ueDl->maxRb; + } + else + { +#ifdef LTE_ADV + if(RFAILED == rgSCHLaaCmn2CwAdjustPrb(allocInfo, boTmp, &numRb, ueDl, noLyr1, noLyr2, iTbs1, iTbs2)) +#endif + { + while ((numRb <= ueDl->maxRb) && + (rgTbSzTbl[noLyr1 - 1][iTbs1][numRb-1] <= ueDl->maxTbSz) && + (rgTbSzTbl[noLyr2 - 1][iTbs2][numRb-1] <= ueDl->maxTbSz) && + ((rgTbSzTbl[noLyr1 - 1][iTbs1][numRb-1]/8 + + rgTbSzTbl[noLyr2 - 1][iTbs2][numRb-1]/8) <= bo)) + { + (numRb)++; + } + } + } + availBw = subFrm->bw - subFrm->bwAssigned; + /* Cannot exceed the total number of RBs in the cell */ + if ((S16)(numRb - allocInfo->rbsReq) > availBw) + { + numRb = availBw + allocInfo->rbsReq; + } + tb1Sz = rgTbSzTbl[noLyr1 - 1][iTbs1][numRb-1]/8; + tb2Sz = rgTbSzTbl[noLyr2 - 1][iTbs2][numRb-1]/8; + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD + if(subFrm->sfType == RG_SCH_SPL_SF_DATA) + { + /* Max Rb for Special Sf is approximated as 4/3 of maxRb */ + rgSCHCmnCalcDwPtsTbSz2Cw(cell, bo, (U8*)&numRb, ueDl->maxRb*4/3, + &iTbs1, &iTbs2, noLyr1, + noLyr2, &tb1Sz, &tb2Sz, cfi); + /* Check for available Bw */ + if ((S16)numRb - allocInfo->rbsReq > availBw) + { + numRb = availBw + allocInfo->rbsReq; + tb1Sz = rgTbSzTbl[noLyr1-1][iTbs1][RGSCH_MAX(numRb*3/4,1)-1]/8; + tb2Sz = rgTbSzTbl[noLyr2-1][iTbs2][RGSCH_MAX(numRb*3/4,1)-1]/8; + } + } +#endif + /* DwPts Scheduling Changes End */ + /* Update the subframe Allocated BW field */ + subFrm->bwAssigned = subFrm->bwAssigned + numRb - \ + allocInfo->rbsReq; + + *effBo = RGSCH_MIN((tb1Sz + tb2Sz) - oldReq, reqBytes); + +#ifdef LTE_ADV + if (ROK != rgSCHLaaCmn2TBPrbCheck(allocInfo, tb1Sz, tb2Sz, boTmp, effBo, iTbs1, iTbs2, numRb, proc)) + { + RETVALUE(RFAILED); + } +#endif + + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs1, imcs1); + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs2, imcs2); + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[0], tb1Sz, \ + iTbs1, imcs1, &proc->tbInfo[0], noLyr1); + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[1], tb2Sz, \ + iTbs2, imcs2, &proc->tbInfo[1], noLyr2); + *numRbRef = (U8)numRb; + + + RETVALUE(ROK); +} + + +/** + * @brief This function determines the RBs and Bytes required for + * Transmission & Retransmission on 2 CWs. + * + * @details + * + * Function: rgSCHCmnDlAlloc2CwTxRetxRb + * Purpose: This function determines the RBs and Bytes required + * for Transmission & Retransmission on 2 CWs. Allocate + * RETX TB on a better CW and restrict new TX TB by + * RETX allocation. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: TM3 and TM4 DL UE Allocation + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqTbCb *reTxTb + * @param[in] RgSchDlHqTbCb *txTb + * @param[out] U8 *numRb + * @param[out] U32 *effBo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRetxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *reTxTb, +RgSchDlHqTbCb *txTb, +U8 *numRb, +U32 *effBo +) +#else +PRIVATE S16 rgSCHCmnDlAlloc2CwTxRetxRb(cell, subFrm, ue, reTxTb, txTb, numRb,\ + effBo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +RgSchDlHqTbCb *reTxTb; +RgSchDlHqTbCb *txTb; +U8 *numRb; +U32 *effBo; +#endif +{ + RgSchCmnDlUe *ueDl; + RgSchDlRbAlloc *allocInfo; + U8 imcs1, imcs2; + U8 noLyr2; + U16 tb2Sz; + RgSchCmnDlUeCwInfo *otherCw; + S16 availBw; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U8 cfi = cellDl->currCfi; + U8 iTbs; + + TRC2(rgSCHCmnDlAlloc2CwTxRetxRb); + + ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + otherCw = &ueDl->mimoInfo.cwInfo[!(ueDl->mimoInfo.btrCwIdx)]; + + + /* Fix for ccpu00123919: In case of RETX TB scheduling avoiding recomputation of RB + * and Tbs. Set all parameters same as Init TX except RV(only for NACKED) and + * MCS. */ + availBw = subFrm->bw - subFrm->bwAssigned; + *numRb = reTxTb->dlGrnt.numRb; + +#ifdef XEON_TDD_SPCL + *numRb = (reTxTb->initTxNumRbs); + if(reTxTb->sfType == RG_SCH_SPL_SF_DATA && subFrm->sfType != RG_SCH_SPL_SF_DATA) + { + *numRb = (reTxTb->initTxNumRbs*3/4); + + if(*numRb <= 3) + { + RLOG1(L_ERROR," Number of RBs [%d] are less than or equal to 3",*numRb); + RETVALUE(RFAILED); + } + } +#endif + + if ((S16)*numRb > availBw) + { + RETVALUE(RFAILED); + } + /* Update the subframe Allocated BW field */ + subFrm->bwAssigned += *numRb; + noLyr2 = otherCw->noLyr; + RG_SCH_CMN_GET_MCS_FOR_RETX(reTxTb, imcs1); + + /* If there is no CFI change, continue to use the BLER based + * iTBS value */ + if (ueDl->lastCfi == cfi) + { + iTbs = otherCw->iTbs[noLyr2-1]; + } + else + { +#ifdef LTE_TDD + iTbs = (U8) rgSchCmnFetchItbs(cell, ueDl, subFrm, otherCw->cqi, cfi, + !(ueDl->mimoInfo.btrCwIdx), noLyr2); +#else + iTbs = (U8) rgSchCmnFetchItbs(cell, ueDl, otherCw->cqi, cfi, + !(ueDl->mimoInfo.btrCwIdx), noLyr2); +#endif + } + tb2Sz = rgTbSzTbl[noLyr2-1][iTbs][*numRb-1]/8; + /* DwPts Scheduling Changes Start */ +#ifdef LTE_TDD +#endif + /* DwPts Scheduling Changes End */ + RG_SCH_CMN_DL_TBS_TO_MCS(iTbs, imcs2); + + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[0], reTxTb->tbSz, \ + 0, imcs1, reTxTb, reTxTb->numLyrs); + + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[1], tb2Sz, \ + iTbs, imcs2, txTb, noLyr2); + + *effBo = reTxTb->tbSz + tb2Sz; + + RETVALUE(ROK); +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * Retransmission on 2 CWs. + * + * @details + * + * Function: rgSCHCmnDlAlloc2CwRetxRb + * Purpose: This function determines the RBs and Bytes required + * for BO Retransmission on 2 CWs. Allocate larger TB + * on a better CW and check if the smaller TB can be + * accomodated on the other CW. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqProcCb *proc + * @param[out] U8 *numRb + * @param[out] Bool *swpFlg + * @param[out] U32 *effBo + * @return Void + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlAlloc2CwRetxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqProcCb *proc, +U8 *numRb, +Bool *swpFlg, +U32 *effBo +) +#else +PRIVATE S16 rgSCHCmnDlAlloc2CwRetxRb(cell, subFrm, ue, proc,\ + numRb, swpFlg, effBo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +RgSchDlHqProcCb *proc; +U8 *numRb; +Bool *swpFlg; +U32 *effBo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + U8 imcs1; + U8 imcs2; + RgSchDlHqTbCb *lrgTbInfo, *othrTbInfo; + + TRC2(rgSCHCmnDlAlloc2CwRetxRb); + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + + /* Fix for ccpu00123919: In case of RETX TB scheduling avoiding recomputation of RB + * and Tbs. Set all parameters same as Init TX except RV(only for NACKED) and + * MCS. */ + lrgTbInfo = &proc->tbInfo[0]; + othrTbInfo = &proc->tbInfo[1]; + *numRb = lrgTbInfo->dlGrnt.numRb; +#ifdef XEON_TDD_SPCL + if((lrgTbInfo->sfType == RG_SCH_SPL_SF_DATA || othrTbInfo->sfType == RG_SCH_SPL_SF_DATA)) + { + if(lrgTbInfo->sfType == RG_SCH_SPL_SF_DATA) + { + *numRb = (lrgTbInfo->initTxNumRbs); + } + else + { + *numRb = (othrTbInfo->initTxNumRbs); + } + + if(subFrm->sfType != RG_SCH_SPL_SF_DATA) + { + *numRb = (*numRb)*3/4; + } + + if(*numRb <= 3) + { + RLOG1(L_ERROR," Number of RBs [%d] are less than or equal to 3",*numRb); + RETVALUE(RFAILED); + } + } +#endif + if ((S16)*numRb > (S16)(subFrm->bw - subFrm->bwAssigned)) + { + RETVALUE(RFAILED); + } + /* Update the subframe Allocated BW field */ + subFrm->bwAssigned += *numRb; + RG_SCH_CMN_GET_MCS_FOR_RETX(lrgTbInfo, imcs1); + RG_SCH_CMN_GET_MCS_FOR_RETX(othrTbInfo, imcs2); + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[0], lrgTbInfo->tbSz, \ + 0, imcs1, lrgTbInfo, lrgTbInfo->numLyrs); + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[1], othrTbInfo->tbSz, \ + 0, imcs2, othrTbInfo, othrTbInfo->numLyrs); + *effBo = lrgTbInfo->tbSz + othrTbInfo->tbSz; + + + + RETVALUE(ROK); +} + + +/** + * @brief This function determines the RBs and Bytes required for BO + * Retransmission on 1 CW. + * + * @details + * + * Function: rgSCHCmnDlAlloc1CwRetxRb + * Purpose: This function determines the RBs and Bytes required + * for BO Retransmission on 1 CW, the first CW. + * Returns RFAILED if BO not satisfied at all. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlSf *subFrm + * @param[in] RgSchUeCb *ue + * @param[in] RgSchDlHqTbCb *tbInfo + * @param[in] U8 noLyr + * @param[out] U8 *numRb + * @param[out] U32 *effBo + * @return S16 + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnDlAlloc1CwRetxRb +( +RgSchCellCb *cell, +RgSchDlSf *subFrm, +RgSchUeCb *ue, +RgSchDlHqTbCb *tbInfo, +U8 noLyr, +U8 *numRb, +U32 *effBo +) +#else +PRIVATE S16 rgSCHCmnDlAlloc1CwRetxRb(cell, subFrm, ue, tbInfo, noLyr,\ + numRb, effBo) +RgSchCellCb *cell; +RgSchDlSf *subFrm; +RgSchUeCb *ue; +RgSchDlHqTbCb *tbInfo; +U8 noLyr; +U8 *numRb; +U32 *effBo; +#endif +{ + RgSchDlRbAlloc *allocInfo; + U8 imcs; + + TRC2(rgSCHCmnDlAlloc1CwRetxRb); + + allocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue,cell); + + + /* Fix for ccpu00123919: In case of RETX TB scheduling avoiding recomputation of RB + * and Tbs. Set all parameters same as Init TX except RV(only for NACKED) and + * MCS. */ + *numRb = tbInfo->dlGrnt.numRb; + if ((S16)*numRb > (S16)(subFrm->bw - subFrm->bwAssigned)) + { + RETVALUE(RFAILED); + } + /* Update the subframe Allocated BW field */ + subFrm->bwAssigned += *numRb; + imcs = tbInfo->dlGrnt.iMcs; + allocInfo->dciFormat = tbInfo->dlGrnt.dciFormat; + /* Fix: For a RETX TB the iTbs is irrelevant, hence setting 0 */ + RG_SCH_CMN_FILL_DL_TBINFO(&allocInfo->tbInfo[0], tbInfo->tbSz, \ + 0, imcs, tbInfo, tbInfo->numLyrs); + *effBo = tbInfo->tbSz; + + RETVALUE(ROK); +} + +#ifdef LTEMAC_SPS + +/** + * @brief This function is called to handle Release PDCCH feedback for SPS UE + * + * @details + * + * Function: rgSCHCmnDlRelPdcchFbk + * Purpose: Invokes SPS module to handle release PDCCH feedback + * + * Invoked by: DHM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] Bool isAck + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlRelPdcchFbk +( +RgSchCellCb *cell, +RgSchUeCb *ue, +Bool isAck +) +#else +PUBLIC Void rgSCHCmnDlRelPdcchFbk(cell, ue, isAck) +RgSchCellCb *cell; +RgSchUeCb *ue; +Bool isAck; +#endif +{ + + TRC2(rgSCHCmnDlRelPdcchFbk); + rgSCHCmnSpsDlRelPdcchFbk(cell, ue, isAck); + RETVOID; + +} + + +/** + * @brief This function is invoked to handle Ack processing for a HARQ proc. + * + * @details + * + * Function: rgSCHCmnDlProcAck + * Purpose: DTX processing for HARQ proc + * + * Invoked by: DHM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlProcAck +( +RgSchCellCb *cell, +RgSchDlHqProcCb *hqP +) +#else +PUBLIC Void rgSCHCmnDlProcAck(cell, hqP) +RgSchCellCb *cell; +RgSchDlHqProcCb *hqP; +#endif +{ + + TRC2(rgSCHCmnDlProcAck); + + if (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) + { + /* Invoke SPS module if SPS service was scheduled for this HARQ proc */ + rgSCHCmnSpsDlProcAck(cell, hqP); + } + RETVOID; +} +#ifdef RGSCH_SPS_STATS +extern U32 rgSchStatCrntiCeRcvCnt; +#endif +/** + * @brief This function is invoked to handle CRNTI CE reception for an UE + * + * @details + * + * Function: rgSCHCmnHdlCrntiCE + * Purpose: Handle CRNTI CE reception + * + * Invoked by: DHM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlHqProcCb *hqP + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnHdlCrntiCE +( +RgSchCellCb *cell, +RgSchUeCb *ue +) +#else +PUBLIC Void rgSCHCmnHdlCrntiCE(cell, ue) +RgSchCellCb *cell; +RgSchUeCb *ue; +#endif +{ + + TRC2(rgSCHCmnHdlCrntiCE); +#ifdef RGSCH_SPS_STATS + rgSchStatCrntiCeRcvCnt++; +#endif + + /* When UL sync lost happened due to TA timer expiry UE is being moved to + PDCCH order inactivity list.But when CRNTI CE received in msg3 from UE + we are not moving UE into active state due to that RRC Reconfiguration is + not happening. + So here we are moving UE to active list whenever we receive the CRNTI CE and + UE is inactive */ + /* CR ccpu00144525 */ + if (RG_SCH_CMN_IS_UE_PDCCHODR_INACTV(ue)) + { + /* Activate this UE if it was inactive */ + RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_PDCCHODR_INACTIVE); + RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_PDCCHODR_INACTIVE); + } + + /* Handling is same as reception of UE RESET for both DL and UL */ + if (ue->dl.dlSpsCfg.isDlSpsEnabled) + { + rgSCHCmnSpsDlUeReset(cell, ue); + } + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlUeReset(cell, ue); + } + + RETVOID; +} + + +/** + * @brief This function is called to handle relInd from MAC for a UE + * + * @details + * + * Function: rgSCHCmnUlSpsRelInd + * Purpose: Invokes SPS module to handle UL SPS release for a UE + * + * Invoked by: SCH_UTL + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] Bool isExplRel + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlSpsRelInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +Bool isExplRel +) +#else +PUBLIC Void rgSCHCmnUlSpsRelInd(cell, ue, isExplRel) +RgSchCellCb *cell; +RgSchUeCb *ue; +Bool isExplRel; +#endif +{ + + TRC2(rgSCHCmnUlSpsRelInd); + rgSCHCmnSpsUlProcRelInd(cell, ue, isExplRel); + RETVOID; + +} /* end of rgSCHCmnUlSpsRelInd */ + +/** + * @brief This function is called to handle SPS Activate Ind from MAC for a UE + * + * @details + * + * Function: rgSCHCmnUlSpsActInd + * Purpose: Invokes SPS module to handle UL SPS activate for a UE + * + * Invoked by: SCH_UTL + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlSpsActInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U16 spsSduSize +) +#else +PUBLIC Void rgSCHCmnUlSpsActInd(cell, ue,spsSduSize) +RgSchCellCb *cell; +RgSchUeCb *ue; +U16 spsSduSize; +#endif +{ + + TRC2(rgSCHCmnUlSpsActInd); + + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlProcActInd(cell, ue,spsSduSize); + } + RETVOID; + +} /* end of rgSCHCmnUlSpsActInd */ + +/** + * @brief This function is called to handle CRC in UL for UEs + * undergoing SPS release + * + * @details + * + * Function: rgSCHCmnUlCrcInd + * Purpose: Invokes SPS module to handle CRC in UL for SPS UE + * + * Invoked by: SCH_UTL + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] CmLteTimingInfo crcTime + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlCrcInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteTimingInfo crcTime +) +#else +PUBLIC Void rgSCHCmnUlCrcInd(cell, ue, crcTime) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteTimingInfo crcTime; +#endif +{ + + TRC2(rgSCHCmnUlCrcInd); + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlProcCrcInd(cell, ue, crcTime); + } + RETVOID; + +} /* end of rgSCHCmnUlCrcFailInd */ + +/** + * @brief This function is called to handle CRC failure in UL + * + * @details + * + * Function: rgSCHCmnUlCrcFailInd + * Purpose: Invokes SPS module to handle CRC failure in UL for SPS UE + * + * Invoked by: SCH_UTL + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] CmLteTimingInfo crcTime + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUlCrcFailInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +CmLteTimingInfo crcTime +) +#else +PUBLIC Void rgSCHCmnUlCrcFailInd(cell, ue, crcTime) +RgSchCellCb *cell; +RgSchUeCb *ue; +CmLteTimingInfo crcTime; +#endif +{ + + TRC2(rgSCHCmnUlCrcFailInd); + if (ue->ul.ulSpsCfg.isUlSpsEnabled == TRUE) + { + rgSCHCmnSpsUlProcDtxInd(cell, ue, crcTime); + } + RETVOID; + +} /* end of rgSCHCmnUlCrcFailInd */ + +#endif /* LTEMAC_SPS */ + +/** + * @brief BCH,BCCH,PCCH Dowlink Scheduling Handler. + * + * @details + * + * Function: rgSCHCmnDlBcchPcchAlloc + * Purpose: This function calls common scheduler APIs to + * schedule for BCCH/PCCH. + * It then invokes Allocator for actual RB + * allocations. It processes on the actual resources allocated + * against requested to the allocator module. + * + * Invoked by: Common Scheduler + * + * @param[in] RgSchCellCb *cell + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnDlBcchPcchAlloc +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnDlBcchPcchAlloc(cell) +RgSchCellCb *cell; +#endif +{ +#ifdef LTE_TDD + U8 nextSfIdx = (cell->crntSfIdx) % RGSCH_SF_ALLOC_SIZE; +#else +#ifdef LTEMAC_HDFDD + U8 nextSfIdx = (cell->crntSfIdx + RG_SCH_CMN_HARQ_INTERVAL) % RGSCH_NUM_SUB_FRAMES; +#else + U8 nextSfIdx = (cell->crntSfIdx) % RGSCH_NUM_SUB_FRAMES; +#endif +#endif + RgInfSfAlloc *nextsfAlloc = &(cell->sfAllocArr[nextSfIdx]); + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + RgSchCmnDlRbAllocInfo *allocInfo = &cellSch->allocInfo; + + TRC2(rgSCHCmnDlBcchPcchAlloc); + + + /*Reset the bitmask for BCCH/PCCH*/ + rgSCHUtlResetSfAlloc(nextsfAlloc,TRUE,FALSE); +#ifndef DISABLE_MIB_SIB /* Not sending MIB and SIB to CL */ +#ifdef RGR_SI_SCH + rgSCHChkNUpdSiCfg(cell); + rgSCHSelectSi(cell); +#endif + + /*Perform the scheduling for BCCH,PCCH*/ + rgSCHCmnDlBcchPcch(cell, allocInfo, nextsfAlloc); + + /* Call common allocator for RB Allocation */ + rgSCHBcchPcchDlRbAlloc(cell, allocInfo); + + /* Finalize the Allocations for reqested Against alloced */ + rgSCHCmnDlBcchPcchFnlz(cell, allocInfo); +#endif /* DISABLE_MIB_SIB */ + RETVOID; +} + +/** + * @brief Handles RB allocation for BCCH/PCCH for downlink. + * + * @details + * + * Function : rgSCHBcchPcchDlRbAlloc + * + * Invoking Module Processing: + * - This function is invoked for DL RB allocation of BCCH/PCCH + * + * Processing Steps: + * - If cell is frequency selecive, + * - Call rgSCHDlfsBcchPcchAllocRb(). + * - else, + * - Do the processing + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchDlRbAllocInfo *allocInfo + * @return Void + **/ + +#ifdef ANSI +PRIVATE Void rgSCHBcchPcchDlRbAlloc +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHBcchPcchDlRbAlloc(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSCHBcchPcchDlRbAlloc); + + + if (cellSch->dl.isDlFreqSel) + { + cellSch->apisDlfs->rgSCHDlfsBcchPcchAllocRb(cell, allocInfo); + } + else + { + rgSCHCmnNonDlfsBcchPcchRbAlloc(cell, allocInfo); + } + + RETVOID; +} + +/** + * @brief Handles RB allocation for BCCH,PCCH for frequency + * non-selective cell. + * + * @details + * + * Function : rgSCHCmnNonDlfsBcchPcchRbAlloc + * + * Invoking Module Processing: + * - SCH shall invoke this if downlink frequency selective is disabled for + * the cell for RB allocation. + * - MAX C/I/PFS/RR shall provide the requiredBytes, required RBs + * estimate and subframe for each allocation to be made to SCH. + * + * Processing Steps: + * - Allocate sequentially for BCCH,PCCH common channels. + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchCmnDlRbAllocInfo *allocInfo + * @return Void + **/ + +#ifdef ANSI +PRIVATE Void rgSCHCmnNonDlfsBcchPcchRbAlloc +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo +) +#else +PRIVATE Void rgSCHCmnNonDlfsBcchPcchRbAlloc(cell, allocInfo) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +#endif +{ + RgSchDlRbAlloc *reqAllocInfo; + + TRC2(rgSCHCmnNonDlfsBcchPcchRbAlloc); + + /* 143473 */ + /* Allocate for PCCH */ + reqAllocInfo = &(allocInfo->pcchAlloc); + if (reqAllocInfo->rbsReq) + { + rgSCHCmnNonDlfsCmnRbAlloc(cell, reqAllocInfo); + } + /* Allocate for BCCH on DLSCH */ + reqAllocInfo = &(allocInfo->bcchAlloc); + if (reqAllocInfo->rbsReq) + { + rgSCHCmnNonDlfsCmnRbAlloc(cell, reqAllocInfo); + } + RETVOID; +} + + +#ifdef RGR_SI_SCH +/** + * @brief This function implements the handling to check and + * update the SI cfg at the start of the modificiation period. + * + * @details + * + * Function: rgSCHChkNUpdSiCfg + * Purpose: This function implements handling for update of SI Cfg + * at the start of modification period. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE Void rgSCHChkNUpdSiCfg +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHChkNUpdSiCfg(cell) +RgSchCellCb *cell; +#endif +{ + CmLteTimingInfo pdSchTmInfo; + + TRC2(rgSCHChkNUpdSiCfg); + + + pdSchTmInfo = cell->crntTime; +#ifdef LTEMAC_HDFDD + /* For HDFDD we need scheduling information at least RG_SCH_CMN_DL_DELTA + + RG_SCH_CMN_HARQ_INTERVAL (7) subframes ahead */ + RGSCH_INCR_SUB_FRAME(pdSchTmInfo, RG_SCH_CMN_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL); +#else + RGSCH_INCR_SUB_FRAME(pdSchTmInfo, RG_SCH_CMN_DL_DELTA); +#endif + + + /* Updating the SIB1 for Warning SI message immediately after it is received + * from application. No need to wait for next modification period. + */ + if((pdSchTmInfo.sfn % RGSCH_SIB1_RPT_PERIODICITY == 0) + && (RGSCH_SIB1_TX_SF_NUM == (pdSchTmInfo.subframe % RGSCH_NUM_SUB_FRAMES))) + { + /*Check whether SIB1 with PWS has been updated*/ + if(cell->siCb.siBitMask & RGSCH_SI_SIB1_PWS_UPD) + { + RGSCH_SET_SI_INFO(cell->siCb.crntSiInfo.sib1Info.sib1, + cell->siCb.newSiInfo.sib1Info.sib1); + cell->siCb.crntSiInfo.sib1Info.mcs = + cell->siCb.newSiInfo.sib1Info.mcs; + cell->siCb.crntSiInfo.sib1Info.nPrb = + cell->siCb.newSiInfo.sib1Info.nPrb; + cell->siCb.crntSiInfo.sib1Info.msgLen = + cell->siCb.newSiInfo.sib1Info.msgLen; + cell->siCb.siBitMask &= ~RGSCH_SI_SIB1_PWS_UPD; + } + } + + /*Check if this SFN and SF No marks the start of next modification + period. If current SFN,SF No doesn't marks the start of next + modification period, then return. */ + if(!((pdSchTmInfo.sfn % cell->siCfg.modPrd == 0) + && (0 == pdSchTmInfo.subframe))) + /*if(!((((pdSchTmInfo.hSfn * 1024) + pdSchTmInfo.sfn) % cell->siCfg.modPrd == 0) + && (0 == pdSchTmInfo.subframe)))*/ + { + RETVOID; + } + + /*Check whether MIB has been updated*/ + if(cell->siCb.siBitMask & RGSCH_SI_MIB_UPD) + { + RGSCH_SET_SI_INFO(cell->siCb.crntSiInfo.mib, + cell->siCb.newSiInfo.mib); + cell->siCb.siBitMask &= ~RGSCH_SI_MIB_UPD; + } + + /*Check whether SIB1 has been updated*/ + if(cell->siCb.siBitMask & RGSCH_SI_SIB1_UPD) + { + RGSCH_SET_SI_INFO(cell->siCb.crntSiInfo.sib1Info.sib1, + cell->siCb.newSiInfo.sib1Info.sib1); + cell->siCb.crntSiInfo.sib1Info.mcs = cell->siCb.newSiInfo.sib1Info.mcs; + cell->siCb.crntSiInfo.sib1Info.nPrb = cell->siCb.newSiInfo.sib1Info.nPrb; + cell->siCb.crntSiInfo.sib1Info.msgLen = + cell->siCb.newSiInfo.sib1Info.msgLen; + cell->siCb.siBitMask &= ~RGSCH_SI_SIB1_UPD; + } + + /*Check whether SIs have been updated*/ + if(cell->siCb.siBitMask & RGSCH_SI_SI_UPD) + { + U8 idx; + + /*Check if SI cfg have been modified And Check if numSi have + been changed, if yes then we would need to update the + pointers for all the SIs */ + if((cell->siCb.siBitMask & RGSCH_SI_SICFG_UPD) && + (cell->siCfg.numSi != cell->siCb.newSiCfg.numSi)) + { + for(idx = 0;idx < cell->siCb.newSiCfg.numSi;idx++) + { + RGSCH_SET_SI_INFO(cell->siCb.crntSiInfo.siInfo[idx].si, + cell->siCb.newSiInfo.siInfo[idx].si); + cell->siCb.siArray[idx].si = cell->siCb.crntSiInfo.siInfo[idx].si; + cell->siCb.siArray[idx].isWarningSi = FALSE; + + cell->siCb.crntSiInfo.siInfo[idx].mcs = cell->siCb.newSiInfo.siInfo[idx].mcs; + cell->siCb.crntSiInfo.siInfo[idx].nPrb = cell->siCb.newSiInfo.siInfo[idx].nPrb; + cell->siCb.crntSiInfo.siInfo[idx].msgLen = cell->siCb.newSiInfo.siInfo[idx].msgLen; + } + + /*If numSi have been reduced then we need to free the + pointers at the indexes in crntSiInfo which haven't + been exercised. If numSi has increased then nothing + additional is requires as above handling has taken + care.*/ + if(cell->siCfg.numSi > cell->siCb.newSiCfg.numSi) + { + for(idx = cell->siCb.newSiCfg.numSi; + idx < cell->siCfg.numSi;idx++) + { + RGSCH_FREE_MSG(cell->siCb.crntSiInfo.siInfo[idx].si); + cell->siCb.siArray[idx].si = NULLP; + } + } + } + else + { + /*numSi has not been updated, we just need to update the + pointers for the SIs which are set to NON NULLP */ + /*ccpu00118260 - Correct Update of SIB2 */ + for(idx = 0;idx < cell->siCfg.numSi;idx++) + { + if(NULLP != cell->siCb.newSiInfo.siInfo[idx].si) + { + RGSCH_SET_SI_INFO(cell->siCb.crntSiInfo.siInfo[idx].si, + cell->siCb.newSiInfo.siInfo[idx].si); + + cell->siCb.siArray[idx].si = cell->siCb.crntSiInfo.siInfo[idx].si; + cell->siCb.siArray[idx].isWarningSi = FALSE; + cell->siCb.crntSiInfo.siInfo[idx].mcs = cell->siCb.newSiInfo.siInfo[idx].mcs; + cell->siCb.crntSiInfo.siInfo[idx].nPrb = cell->siCb.newSiInfo.siInfo[idx].nPrb; + cell->siCb.crntSiInfo.siInfo[idx].msgLen = cell->siCb.newSiInfo.siInfo[idx].msgLen; + } + } + } + cell->siCb.siBitMask &= ~RGSCH_SI_SI_UPD; + } + + /*Check whether SI cfg have been updated*/ + if(cell->siCb.siBitMask & RGSCH_SI_SICFG_UPD) + { + cell->siCfg = cell->siCb.newSiCfg; + cell->siCb.siBitMask &= ~RGSCH_SI_SICFG_UPD; + } + + RETVOID; +} + + +/** + * @brief This function implements the selection of the SI + * that is to be scheduled. + * + * @details + * + * Function: rgSCHSelectSi + * Purpose: This function implements the selection of SI + * that is to be scheduled. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE Void rgSCHSelectSi +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHSelectSi(cell) +RgSchCellCb *cell; +#endif +{ + CmLteTimingInfo crntTmInfo; + U8 siWinSize; + U16 x; + U16 windowId; + + TRC2(rgSCHSelectSi); + + + crntTmInfo = cell->crntTime; +#ifdef LTEMAC_HDFDD + /* For HDFDD we need scheduling information at least RG_SCH_CMN_DL_DELTA + + RG_SCH_CMN_HARQ_INTERVAL (7) subframes ahead */ + RGSCH_INCR_SUB_FRAME(crntTmInfo, RG_SCH_CMN_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL); +#else + RGSCH_INCR_SUB_FRAME(crntTmInfo, RG_SCH_CMN_DL_DELTA); +#endif + + siWinSize = cell->siCfg.siWinSize; + + /* Select SI only once at the starting of the new window */ + if(cell->siCb.inWindow) + { + if ((crntTmInfo.sfn % cell->siCfg.minPeriodicity) == 0 && + crntTmInfo.subframe == 0) + { + /* Reinit inWindow at the beginning of every SI window */ + cell->siCb.inWindow = siWinSize - 1; + } + else + { + cell->siCb.inWindow--; + RETVOID; + } + } + else /* New window. Re-init the winSize counter with the window length */ + { + if((cell->siCb.siArray[cell->siCb.siCtx.siId - 1].isWarningSi == TRUE)&& + (cell->siCb.siCtx.retxCntRem != 0)) + { + rgSCHUtlFreeWarningSiPdu(cell); + cell->siCb.siCtx.warningSiFlag = FALSE; + } + + cell->siCb.inWindow = siWinSize - 1; + } + + x = rgSCHCmnGetSiSetId(crntTmInfo.sfn, crntTmInfo.subframe, + cell->siCfg.minPeriodicity); + + /* Window Id within a SI set. This window Id directly maps to a + * unique SI Id */ + windowId = (((crntTmInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G) + + crntTmInfo.subframe) - (x * (cell->siCfg.minPeriodicity * 10))) + / siWinSize; + + if(windowId >= RGR_MAX_NUM_SI) + RETVOID; + + /* Update the siCtx if there is a valid SI and its periodicity + * has occurred */ + if (NULLP != cell->siCb.siArray[windowId].si) + { + /* Warning SI Periodicity is same as SIB2 Periodicity */ + if(((cell->siCb.siArray[windowId].isWarningSi == FALSE) && + (x % (cell->siCfg.siPeriodicity[windowId] + /cell->siCfg.minPeriodicity) == 0)) || + ((cell->siCb.siArray[windowId].isWarningSi == TRUE) && + (x % (cell->siCfg.siPeriodicity[0] + /cell->siCfg.minPeriodicity) == 0))) + { + cell->siCb.siCtx.siId = windowId+1; + cell->siCb.siCtx.retxCntRem = cell->siCfg.retxCnt; + cell->siCb.siCtx.warningSiFlag = cell->siCb.siArray[windowId]. + isWarningSi; + cell->siCb.siCtx.timeToTx.sfn = crntTmInfo.sfn; + cell->siCb.siCtx.timeToTx.subframe = crntTmInfo.subframe; + + RG_SCH_ADD_TO_CRNT_TIME(cell->siCb.siCtx.timeToTx, + cell->siCb.siCtx.maxTimeToTx, (siWinSize - 1)) + } + } + else + {/* Update the siCtx with invalid si Id */ + cell->siCb.siCtx.siId = 0; + } + + RETVOID; +} + + +/** + * @brief This function implements scheduler DL allocation for + * SI. + * + * @details + * + * Function: rgSCHDlSiSched + * Purpose: This function implements scheduler for DL allocation + * for SI. + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb* cell + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PRIVATE Void rgSCHDlSiSched +( +RgSchCellCb *cell, +RgSchCmnDlRbAllocInfo *allocInfo, +RgInfSfAlloc *subfrmAlloc +) +#else +PRIVATE Void rgSCHDlSiSched(cell, allocInfo, subfrmAlloc) +RgSchCellCb *cell; +RgSchCmnDlRbAllocInfo *allocInfo; +RgInfSfAlloc *subfrmAlloc; +#endif +{ + CmLteTimingInfo crntTimInfo; + RgSchDlSf *sf; + U8 nPrb = 0; + U8 mcs = 0; + MsgLen msgLen = 0; + U32 rb=0; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + U16 lostRe; + U8 cfi = cellDl->currCfi; +#endif + /* DwPTS Scheduling Changes End */ + + TRC2(rgSCHDlSiSched); + + + crntTimInfo = cell->crntTime; +#ifdef LTEMAC_HDFDD + /* For HDFDD we need scheduling information at least RG_SCH_CMN_DL_DELTA + + RG_SCH_CMN_HARQ_INTERVAL (7) subframes ahead */ + RGSCH_INCR_SUB_FRAME(crntTimInfo, RG_SCH_CMN_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL); +#else + RGSCH_INCR_SUB_FRAME(crntTimInfo, RG_SCH_CMN_DL_DELTA); +#endif + + /* Compute the subframe for which allocation is being made. + Essentially, we need pointer to the dl frame for this subframe */ + sf = rgSCHUtlSubFrmGet(cell, crntTimInfo); + + /*Check if scheduling of MIB is required */ +#ifdef EMTC_ENABLE + /* since we are adding the MIB repetition logic for EMTC UEs, checking if + * emtcEnabled or not, If enabled MIB would be repeted at as part of EMTC + * feature, otherwise scheduling at (n,0) */ + if(0 == cell->emtcEnable) + { +#endif + if((crntTimInfo.sfn % RGSCH_MIB_PERIODICITY == 0) + && (RGSCH_MIB_TX_SF_NUM == crntTimInfo.subframe)) + { + MsgLen mibLen = 0; + U8 sfnOctet, mibOct2 = 0; + U8 mibOct1 = 0; + /*If MIB has not been yet setup by Application, return*/ + if(NULLP == cell->siCb.crntSiInfo.mib) + RETVOID; + + SFndLenMsg(cell->siCb.crntSiInfo.mib, &mibLen); + sf->bch.tbSize = mibLen; + /*Fill the interface information */ + rgSCHUtlFillRgInfCmnLcInfo(sf, subfrmAlloc, NULLD, NULLD); + + /*Set the bits of MIB to reflect SFN */ + /*First get the Most signficant 8 bits of SFN */ + sfnOctet = (U8)(crntTimInfo.sfn >> 2); + /*Get the first two octets of MIB, and then update them + using the SFN octet value obtained above.*/ + if(ROK != SExamMsg((Data *)(&mibOct1), + cell->siCb.crntSiInfo.mib, 0)) + RETVOID; + + if(ROK != SExamMsg((Data *)(&mibOct2), + cell->siCb.crntSiInfo.mib, 1)) + RETVOID; + + /* ccpu00114572- Fix for improper way of MIB Octet setting for SFN */ + mibOct1 = (mibOct1 & 0xFC) | (sfnOctet >> 6); + mibOct2 = (mibOct2 & 0x03) | (sfnOctet << 2); + /* ccpu00114572- Fix ends*/ + + /*Now, replace the two octets in MIB */ + if(ROK != SRepMsg((Data)(mibOct1), + cell->siCb.crntSiInfo.mib, 0)) + RETVOID; + + if(ROK != SRepMsg((Data)(mibOct2), + cell->siCb.crntSiInfo.mib, 1)) + RETVOID; + + /*Copy the MIB msg buff into interface buffer */ + SCpyMsgMsg(cell->siCb.crntSiInfo.mib, + rgSchCb[cell->instIdx].rgSchInit.region, + rgSchCb[cell->instIdx].rgSchInit.pool, + &subfrmAlloc->cmnLcInfo.bchInfo.pdu); + /* Added Dl TB count for MIB message transmission + * This counter is incremented 4 times to consider + * the retransmission at the PHY level on PBCH channel*/ +#ifdef LTE_L2_MEAS + cell->dlUlTbCnt.tbTransDlTotalCnt += RG_SCH_MIB_CNT; +#endif + } +#ifdef EMTC_ENABLE + } +#endif + + allocInfo->bcchAlloc.schdFirst = FALSE; + /*Check if scheduling of SIB1 is required. + Check of (crntTimInfo.sfn % RGSCH_SIB1_PERIODICITY == 0) + is not required here since the below check takes care + of SFNs applicable for this one too.*/ + if((crntTimInfo.sfn % RGSCH_SIB1_RPT_PERIODICITY == 0) + && (RGSCH_SIB1_TX_SF_NUM == crntTimInfo.subframe)) + { + /*If SIB1 has not been yet setup by Application, return*/ + if(NULLP == (cell->siCb.crntSiInfo.sib1Info.sib1)) + { + RETVOID; + } + + allocInfo->bcchAlloc.schdFirst = TRUE; + mcs = cell->siCb.crntSiInfo.sib1Info.mcs; + nPrb = cell->siCb.crntSiInfo.sib1Info.nPrb; + msgLen = cell->siCb.crntSiInfo.sib1Info.msgLen; + } + else + { + /*Check if scheduling of SI can be performed.*/ + Bool invalid = FALSE; + + if(cell->siCb.siCtx.siId == 0) + RETVOID; + + /*Check if the Si-Window for the current Si-Context is completed*/ + invalid = rgSCHCmnChkPastWin(crntTimInfo, cell->siCb.siCtx.maxTimeToTx); + if(invalid) + { + /* LTE_ADV_FLAG_REMOVED_START */ + if(cell->siCb.siCtx.retxCntRem) + { + RGSCHLOGERROR(cell->instIdx,ERRCLS_INT_PAR,ERG011,(ErrVal)cell->siCb.siCtx.siId, + "rgSCHDlSiSched(): SI not scheduled and window expired"); + } + /* LTE_ADV_FLAG_REMOVED_END */ + if(cell->siCb.siCtx.warningSiFlag == TRUE) + { + rgSCHUtlFreeWarningSiPdu(cell); + cell->siCb.siCtx.warningSiFlag = FALSE; + } + RETVOID; + } + + /*Check the timinginfo of the current SI-Context to see if its + transmission can be scheduled. */ + if(FALSE == (rgSCHCmnChkInWin(crntTimInfo, + cell->siCb.siCtx.timeToTx, + cell->siCb.siCtx.maxTimeToTx))) + { + RETVOID; + + } + /*Check if retransmission count has become 0*/ + if(0 == cell->siCb.siCtx.retxCntRem) + { + RETVOID; + } + + /* LTE_ADV_FLAG_REMOVED_START */ + /* Check if ABS is enabled/configured */ + if(RGR_ENABLE == cell->lteAdvCb.absCfg.status) + { + /* The pattern type is RGR_ABS_MUTE, then eNB need to blank the subframe */ + if(cell->lteAdvCb.absCfg.absPatternType & RGR_ABS_MUTE) + { + /* Determine next scheduling subframe is ABS or not */ + if(RG_SCH_ABS_ENABLED_ABS_SF == (RgSchAbsSfEnum)(cell->lteAdvCb.absCfg.absPattern + [((crntTimInfo.sfn*RGSCH_NUM_SUB_FRAMES) + crntTimInfo.subframe) % RGR_ABS_PATTERN_LEN])) + { + /* Skip the SI scheduling to next tti */ + RETVOID; + } + } + } + /* LTE_ADV_FLAG_REMOVED_END */ + + /*Schedule the transmission of the current SI-Context */ + /*Find out the messg length for the SI message */ + /* warningSiFlag is to differentiate between Warning SI + * and Other SI */ + if((rgSCHUtlGetMcsAndNPrb(cell, &nPrb, &mcs, &msgLen)) != ROK) + { + RETVOID; + } + + cell->siCb.siCtx.i = RGSCH_CALC_SF_DIFF(crntTimInfo, + cell->siCb.siCtx.timeToTx); + } + + + /*Get the number of rb required */ + /*rgSCHCmnClcRbAllocForFxdTb(cell, msgLen, cellDl->ccchCqi, &rb);*/ + if(cellDl->bitsPerRb==0) + { + while ((rgTbSzTbl[0][0][rb]) < (U32) (msgLen*8)) + { + rb++; + } + rb = rb+1; + } + else + { + rb = RGSCH_CEIL((msgLen*8), cellDl->bitsPerRb); + } + /* DwPTS Scheduling Changes Start */ +#ifdef LTE_TDD + if (sf->sfType == RG_SCH_SPL_SF_DATA) + { + RGSCH_GET_SPS_SF_CFI(cell->bwCfg.dlTotalBw, cfi); + + /* Calculate the less RE's because of DwPTS */ + lostRe = rb * (cellDl->noResPerRb[cfi] - cellDl->numReDwPts[cfi]); + + /* Increase number of RBs in Spl SF to compensate for lost REs */ + rb += RGSCH_CEIL(lostRe, cellDl->numReDwPts[cfi]); + } +#endif + /* DwPTS Scheduling Changes End */ + /*ccpu00115595- end*/ + /* Additional check to see if required RBs + * exceeds the available */ + if (rb > sf->bw - sf->bwAssigned) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDlSiSched(): " + "BW allocation failed CRNTI:%d",RGSCH_SI_RNTI); + RETVOID; + } + + /* Update the subframe Allocated BW field */ + sf->bwAssigned = sf->bwAssigned + rb; + + /*Fill the parameters in allocInfo */ + allocInfo->bcchAlloc.rnti = RGSCH_SI_RNTI; + allocInfo->bcchAlloc.dlSf = sf; + allocInfo->bcchAlloc.rbsReq = rb; + /*ccpu00116710- MCS is not getting assigned */ + allocInfo->bcchAlloc.tbInfo[0].imcs = mcs; + + /* ccpu00117510 - ADD - Assignment of nPrb and other information */ + allocInfo->bcchAlloc.nPrb = nPrb; + allocInfo->bcchAlloc.tbInfo[0].bytesReq = msgLen; + allocInfo->bcchAlloc.tbInfo[0].noLyr = 1; + RETVOID; +} +#endif /*RGR_SI_SCH*/ + + +/* ccpu00117452 - MOD - Changed macro name from + RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */ +#ifdef RGR_CQI_REPT +/** + * @brief This function Updates the DL CQI for the UE. + * + * @details + * + * Function: rgSCHCmnUeDlPwrCtColltCqiRept + * Purpose: Manages PUSH N CQI reporting + * Step 1: Store the CQI in collation array + * Step 2: Increament the tracking count + * Step 3: Check is it time to to send the report + * Step 4: if yes, Send StaInd to RRM + * Step 4.1: Fill StaInd for sending collated N CQI rpeorts + * Step 4.2: Call utility function (rgSCHUtlRgrStaInd) to send rpts to RRM + * Step 4.2.1: If sending was not sucessful, return RFAILED + * Step 4.2.2: If sending was sucessful, return ROK + * Step 5: If no, return + * Invoked by: rgSCHCmnDlCqiInd + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgrUeCqiRept *ueCqiRpt + * @return Void + * + **/ +#ifdef ANSI +PRIVATE S16 rgSCHCmnUeDlPwrCtColltCqiRept +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgrUeCqiRept *ueCqiRpt +) +#else +PRIVATE S16 rgSCHCmnUeDlPwrCtColltCqiRept(cell, ue, ueCqiRpt) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgrUeCqiRept *ueCqiRpt; +#endif +{ + U8 *cqiCount = NULLP; + S16 retVal; + RgrStaIndInfo *staInfo = NULLP; + + TRC2(rgSCHCmnUeDlPwrCtColltCqiRept) + + /* Step 1: Store the CQI in collation array */ + /* Step 2: Increament the tracking count */ + cqiCount = &(ue->schCqiInfo.cqiCount); + ue->schCqiInfo.cqiRept[(*cqiCount)++] = + *ueCqiRpt; + + + /* Step 3: Check is it time to to send the report */ + if(RG_SCH_CQIR_IS_TIMTOSEND_CQIREPT(ue)) + { + /* Step 4: if yes, Send StaInd to RRM */ + retVal = rgSCHUtlAllocSBuf (cell->instIdx,(Data**)&staInfo, + sizeof(RgrStaIndInfo)); + if (retVal != ROK) + { + RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Could not " + "allocate memory for sending StaInd CRNTI:%d",ue->ueId); + RETVALUE(retVal); + } + + /* Step 4.1: Fill StaInd for sending collated N CQI rpeorts */ +#ifdef CA_DBG + { + extern U32 gCqiReptToAppCount; + gCqiReptToAppCount++; + + } + +#endif + retVal = rgSCHUtlFillSndStaInd(cell, ue, staInfo, + ue->cqiReptCfgInfo.numColltdCqiRept); + RETVALUE(retVal); + + } + + RETVALUE(ROK); +} /* End of rgSCHCmnUeDlPwrCtColltCqiRept */ + +#endif /* End of RGR_CQI_REPT */ + +/** + * @brief This function checks for the retransmisson + * for a DTX scenario. + * @details + * + * Function: + * Purpose: + * Invoked by: + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] + * @return Void + * + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnChkRetxAllowDtx +( +RgSchCellCb *cell, +RgSchUeCb *ueCb, +RgSchDlHqProcCb *proc, +Bool *reTxAllwd +) +#else +PUBLIC Void rgSCHCmnChkRetxAllowDtx(cell, ueCb, proc, reTxAllwd) +RgSchCellCb *cell; +RgSchUeCb *ueCb; +RgSchDlHqProcCb *proc; +Bool *reTxAllwd; +#endif +{ + TRC3(rgSCHCmnChkRetxAllowDtx) + + + *reTxAllwd = TRUE; + /* Fix */ + if ((proc->tbInfo[0].isAckNackDtx == TFU_HQFDB_DTX)) + { + *reTxAllwd = FALSE; + } + + RETVOID; +} + +/** + * @brief API for calculating the SI Set Id + * + * @details + * + * Function: rgSCHCmnGetSiSetId + * + * This API is used for calculating the SI Set Id, as shown below + * + * siSetId = 0 siSetId = 1 + * |******************|******************|----------------> + * (0,0) (8,0) (16,0) (SFN, SF) + * + * + * @param[in] U16 sfn + * @param[in] U8 sf + * @return U16 siSetId + **/ +#ifdef ANSI +PUBLIC U16 rgSCHCmnGetSiSetId +( +U16 sfn, +U8 sf, +U16 minPeriodicity +) +#else +PUBLIC U16 rgSCHCmnGetSiSetId(sfn, sf, minPeriodicity) +U16 sfn; +U8 sf +U16 minPeriodicity; +#endif +{ + /* 80 is the minimum SI periodicity in sf. Also + * all other SI periodicities are multiples of 80 */ + RETVALUE (((sfn * RGSCH_NUM_SUB_FRAMES_5G) + sf) / (minPeriodicity * 10)); +} +#ifdef LTE_TDD +/** + * @brief API for calculating the DwPts Rb, Itbs and tbSz + * + * @details + * + * Function: rgSCHCmnCalcDwPtsTbSz + * + * @param[in] RgSchCellCb *cell + * @param[in] U32 bo + * @param[in/out] U8 *rb + * @param[in/out] U8 *iTbs + * @param[in] U8 lyr + * @param[in] U8 cfi + * @return U32 tbSz + **/ +#ifdef ANSI +PRIVATE U32 rgSCHCmnCalcDwPtsTbSz +( +RgSchCellCb *cell, +U32 bo, +U8 *rb, +U8 *iTbs, +U8 lyr, +U8 cfi +) +#else +PRIVATE U32 rgSCHCmnCalcDwPtsTbSz(cell, bo, rb, iTbs, lyr, cfi) +RgSchCellCb *cell; +U32 bo; +U8 *rb; +U8 *iTbs; +U8 lyr; +U8 cfi; +#endif +{ + U32 tbSz; + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U32 numRE = *rb * cellDl->noResPerRb[cfi]; + U32 numDwPtsRb = RGSCH_CEIL(numRE, cellDl->numReDwPts[cfi]); + + TRC2(rgSCHCmnCalcDwPtsTbSz); + + /* DwPts Rb cannot exceed the cell Bw */ + numDwPtsRb = RGSCH_MIN(numDwPtsRb, cellDl->maxDlBwPerUe); + + /* Adjust the iTbs for optimum usage of the DwPts region. + * Using the same iTbs adjustment will not work for all + * special subframe configurations and iTbs levels. Hence use the + * static iTbs Delta table for adjusting the iTbs */ + RG_SCH_CMN_ADJ_DWPTS_ITBS(cellDl, *iTbs); + + if (bo) + { + while(rgTbSzTbl[lyr-1][*iTbs][RGSCH_MAX(numDwPtsRb*3/4,1)-1] < bo*8 && + numDwPtsRb < cellDl->maxDlBwPerUe) + { + (numDwPtsRb)++; + } + + tbSz = rgTbSzTbl[lyr-1][*iTbs][RGSCH_MAX(numDwPtsRb*3/4,1)-1]; + } + else + { + tbSz = rgTbSzTbl[lyr-1][*iTbs][RGSCH_MAX(numDwPtsRb*3/4,1)-1]; + } + *rb = numDwPtsRb; + + RETVALUE(tbSz/8); +} + +/** + * @brief API for calculating the DwPts Rb, Itbs and tbSz + * + * @details + * + * Function: rgSCHCmnCalcDwPtsTbSz2Cw + * + * @param[in] RgSchCellCb *cell + * @param[in] U32 bo + * @param[in/out] U8 *rb + * @param[in] U8 maxRb + * @param[in/out] U8 *iTbs1 + * @param[in/out] U8 *iTbs2 + * @param[in] U8 lyr1 + * @param[in] U8 lyr2 + * @return[in/out] U32 *tb1Sz + * @return[in/out] U32 *tb2Sz + * @param[in] U8 cfi + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnCalcDwPtsTbSz2Cw +( +RgSchCellCb *cell, +U32 bo, +U8 *rb, +U8 maxRb, +U8 *iTbs1, +U8 *iTbs2, +U8 lyr1, +U8 lyr2, +U32 *tb1Sz, +U32 *tb2Sz, +U8 cfi +) +#else +PRIVATE Void rgSCHCmnCalcDwPtsTbSz2Cw(cell, bo, rb, maxRb, iTbs1, iTbs2, + lyr1, lyr2, tb1Sz, tb2Sz, cfi) +RgSchCellCb *cell; +U32 bo; +U8 *rb; +U8 maxRb; +U8 *iTbs1; +U8 *iTbs2; +U8 lyr1; +U8 lyr2; +U32 *tb1Sz; +U32 *tb2Sz; +U8 cfi; +#endif +{ + RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell); + U32 numRE = *rb * cellDl->noResPerRb[cfi]; + U32 numDwPtsRb = RGSCH_CEIL(numRE, cellDl->numReDwPts[cfi]); + + TRC2(rgSCHCmnCalcDwPtsTbSz2Cw); + + /* DwPts Rb cannot exceed the cell Bw */ + numDwPtsRb = RGSCH_MIN(numDwPtsRb, maxRb); + + /* Adjust the iTbs for optimum usage of the DwPts region. + * Using the same iTbs adjustment will not work for all + * special subframe configurations and iTbs levels. Hence use the + * static iTbs Delta table for adjusting the iTbs */ + RG_SCH_CMN_ADJ_DWPTS_ITBS(cellDl, *iTbs1); + RG_SCH_CMN_ADJ_DWPTS_ITBS(cellDl, *iTbs2); + + while((rgTbSzTbl[lyr1-1][*iTbs1][RGSCH_MAX(numDwPtsRb*3/4,1)-1] + + rgTbSzTbl[lyr2-1][*iTbs2][RGSCH_MAX(numDwPtsRb*3/4,1)-1])< bo*8 && + numDwPtsRb < maxRb) + { + (numDwPtsRb)++; + } + + *tb1Sz = rgTbSzTbl[lyr1-1][*iTbs1][RGSCH_MAX(numDwPtsRb*3/4,1)-1]/8; + *tb2Sz = rgTbSzTbl[lyr2-1][*iTbs2][RGSCH_MAX(numDwPtsRb*3/4,1)-1]/8; + + *rb = numDwPtsRb; + + RETVOID; +} + +#endif + +/** + * @brief Updates the GBR LCGs when datInd is received from MAC + * + * @details + * + * Function: rgSCHCmnUpdUeDataIndLcg(cell, ue, datInd) + * Purpose: This function updates the GBR LCGs + * when datInd is received from MAC. + * + * Invoked by: TOM + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgInfUeDatInd *datInd + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSCHCmnUpdUeDataIndLcg +( +RgSchCellCb *cell, +RgSchUeCb *ue, +RgInfUeDatInd *datInd +) +#else +PUBLIC Void rgSCHCmnUpdUeDataIndLcg(cell, ue, datInd) +RgSchCellCb *cell; +RgSchUeCb *ue; +RgInfUeDatInd *datInd; +#endif +{ + U32 idx = 0; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); +#ifdef DEBUGP + Inst inst = cell->instIdx; +#endif + + TRC2(rgSCHCmnUpdUeDataIndLcg); + + for (idx = 0; (idx < RGINF_MAX_LCG_PER_UE - 1); idx++) + { + if (datInd->lcgInfo[idx].bytesRcvd != 0) + { + U8 lcgId = datInd->lcgInfo[idx].lcgId; + U32 bytesRcvd = datInd->lcgInfo[idx].bytesRcvd; + + if (RGSCH_LCG_ISCFGD(&ue->ul.lcgArr[lcgId])) + { + RgSchCmnLcg *cmnLcg = ((RgSchCmnLcg *)(ue->ul.lcgArr[lcgId].sch)); + if (RGSCH_IS_GBR_BEARER(cmnLcg->cfgdGbr)) + { + if(bytesRcvd > cmnLcg->effGbr) + { + bytesRcvd -= cmnLcg->effGbr; + cmnLcg->effDeltaMbr = (cmnLcg->effDeltaMbr > bytesRcvd) ? \ + (cmnLcg->effDeltaMbr - bytesRcvd) : (0); + cmnLcg->effGbr = 0; + } + else + { + cmnLcg->effGbr -= bytesRcvd; + } + /* To keep BS updated with the amount of data received for the GBR */ + cmnLcg->reportedBs = (cmnLcg->reportedBs > datInd->lcgInfo[idx].bytesRcvd) ? \ + (cmnLcg->reportedBs - datInd->lcgInfo[idx].bytesRcvd) : (0); + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, cmnLcg->effGbr+cmnLcg->effDeltaMbr); + } + else if(lcgId != 0) + { + ue->ul.effAmbr = (ue->ul.effAmbr > datInd->lcgInfo[idx].bytesRcvd) ? \ + (ue->ul.effAmbr - datInd->lcgInfo[idx].bytesRcvd) : (0); + cmnLcg->reportedBs = (cmnLcg->reportedBs > datInd->lcgInfo[idx].bytesRcvd) ? \ + (cmnLcg->reportedBs - datInd->lcgInfo[idx].bytesRcvd) : (0); + cmnLcg->bs = RGSCH_MIN(cmnLcg->reportedBs, ue->ul.effAmbr); + ue->ul.nonGbrLcgBs = (ue->ul.nonGbrLcgBs > datInd->lcgInfo[idx].bytesRcvd) ? \ + (ue->ul.nonGbrLcgBs - datInd->lcgInfo[idx].bytesRcvd) : (0); + } + ue->ul.nonLcg0Bs = (ue->ul.nonLcg0Bs > datInd->lcgInfo[idx].bytesRcvd) ? \ + (ue->ul.nonLcg0Bs - datInd->lcgInfo[idx].bytesRcvd) : (0); + } + } + else + { + break; + } + } +#ifdef EMTC_ENABLE + if(TRUE == ue->isEmtcUe) + { + if (cellSch->apisEmtcUl->rgSCHRgrUlLcgUpd(cell, ue, datInd) != ROK) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "\n rgSCHCmnUpdUeDataIndLcg(): rgSCHRgrUlLcgUpd returned failure")); + } + + } + else +#endif + { + if (cellSch->apisUl->rgSCHRgrUlLcgUpd(cell, ue, datInd) != ROK) + { + RGSCHDBGERRNEW(inst, (rgSchPBuf(inst), "\n rgSCHCmnUpdUeDataIndLcg(): rgSCHRgrUlLcgUpd returned failure")); + } + } +} + + +/** @brief This function initializes DL allocation lists and prepares + * for scheduling + * + * @details + * + * Function: rgSCHCmnInitRbAlloc + * + * @param [in] RgSchCellCb *cell + * + * Returns: Void + * + */ +#ifdef ANSI +PRIVATE Void rgSCHCmnInitRbAlloc +( +RgSchCellCb *cell +) +#else +PRIVATE Void rgSCHCmnInitRbAlloc (cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + CmLteTimingInfo frm; + RgSchDlSf *dlSf; + U8 idx; + + TRC2(rgSCHCmnInitRbAlloc); + +/* Initializing RgSchCmnUlRbAllocInfo structure.*/ + rgSCHCmnInitDlRbAllocInfo(&cellSch->allocInfo); + + frm = cellSch->dl.time; + + dlSf = rgSCHUtlSubFrmGet(cell, frm); +#ifdef RG_5GTF + dlSf->numGrpPerTti = cell->cell5gtfCb.ueGrpPerTti; + dlSf->numUePerGrp = cell->cell5gtfCb.uePerGrpPerTti; + for(idx = 0; idx < MAX_5GTF_BEAMS; idx++) + { + dlSf->sfBeamInfo[idx].totVrbgAllocated = 0; + dlSf->sfBeamInfo[idx].totVrbgRequired = 0; + dlSf->sfBeamInfo[idx].vrbgStart = 0; + } +#endif + dlSf->remUeCnt = cellSch->dl.maxUePerDlSf; + /* Updating the Subframe information in RBAllocInfo */ + cellSch->allocInfo.dedAlloc.dedDlSf = dlSf; + cellSch->allocInfo.msg4Alloc.msg4DlSf = dlSf; + + /* LTE_ADV_FLAG_REMOVED_START */ + /* Determine next scheduling subframe is ABS or not */ + if(RGR_ENABLE == cell->lteAdvCb.absCfg.status) + { + cell->lteAdvCb.absPatternDlIdx = + ((frm.sfn*RGSCH_NUM_SUB_FRAMES_5G) + frm.subframe) % RGR_ABS_PATTERN_LEN; + cell->lteAdvCb.absDlSfInfo = (RgSchAbsSfEnum)(cell->lteAdvCb.absCfg.absPattern[ + cell->lteAdvCb.absPatternDlIdx]); + + } + else + { + cell->lteAdvCb.absDlSfInfo = RG_SCH_ABS_DISABLED; + } + /* LTE_ADV_FLAG_REMOVED_END */ + +#ifdef RGR_V1 + cellSch->allocInfo.ccchSduAlloc.ccchSduDlSf = dlSf; +#endif +#ifdef LTEMAC_SPS + /* Update subframe-wide allocation information with SPS allocation */ + rgSCHCmnSpsDlUpdDlSfAllocWithSps(cell, frm, dlSf); +#endif + RETVOID; +} + + + +#ifdef DL_LA +/** + * @brief Check & Updates the TM Mode chnage threashold based on cqiiTbs and + * actual iTbs + * + * @details + * + * Function: rgSCHCmnSendTxModeInd(cell, ueUl, newTxMode) + * Purpose: This function sends the TX mode Change + * indication to RRM + * change + * + * Invoked by: CMN + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 newTxMode + * @return Void + **/ +#ifdef ANSI +PRIVATE Void rgSCHCmnSendTxModeInd +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 newTxMode +) +#else +PRIVATE Void rgSCHCmnSendTxModeInd(cell, ue, newTxMode) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 newTxMode; +#endif +{ + RgmTransModeInd *txModeChgInd; + RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell); + + TRC2(rgSCHCmnSendTxModeInd); + + if(!(ueDl->mimoInfo.forceTD & RG_SCH_CMN_TD_TXMODE_RECFG)) + { + /* Mem Alloc */ + if(SGetSBuf(cell->rgmSap->sapCfg.sapPst.region, + cell->rgmSap->sapCfg.sapPst.pool, (Data**)&txModeChgInd, + sizeof(RgmTransModeInd)) != ROK) + { + RETVOID; + } + RG_SCH_FILL_RGM_TRANSMODE_IND(ue->ueId, cell->cellId, newTxMode, txModeChgInd); + RgUiRgmChangeTransModeInd(&(cell->rgmSap->sapCfg.sapPst), + cell->rgmSap->sapCfg.suId, txModeChgInd); + } + + ue->mimoInfo.txModUpChgFactor = 0; + ue->mimoInfo.txModDownChgFactor = 0; + ueDl->laCb[0].deltaiTbs = 0; + + RETVOID; +} + +/** + * @brief Check & Updates the TM Mode chnage threashold based on cqiiTbs and + * actual iTbs + * + * @details + * + * Function: rgSchCheckAndTriggerModeChange(cell, ueUl, iTbsNew) + * Purpose: This function update and check for threashold for TM mode + * change + * + * Invoked by: CMN + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] U8 iTbs + * @return Void + **/ +#ifdef ANSI +PUBLIC Void rgSchCheckAndTriggerModeChange +( +RgSchCellCb *cell, +RgSchUeCb *ue, +U8 reportediTbs, +U8 previTbs, +U8 maxiTbs +) +#else +PUBLIC Void rgSchCheckAndTriggerModeChange(cell, ue, reportediTbs, previTbs, maxiTbs) +RgSchCellCb *cell; +RgSchUeCb *ue; +U8 reportediTbs; +U8 previTbs; +U8 maxiTbs; +#endif +{ + RgrTxMode txMode; /*!< UE's Transmission Mode */ + RgrTxMode modTxMode; /*!< UE's Transmission Mode */ + + TRC2(rgSchCheckAndTriggerModeChange); + + txMode = ue->mimoInfo.txMode; + + /* Check for Step down */ + /* Step down only when TM4 is configured. */ + if(RGR_UE_TM_4 == txMode) + { + if((previTbs <= reportediTbs) && ((reportediTbs - previTbs) >= RG_SCH_MODE_CHNG_STEPDOWN_CHECK_FACTOR)) + { + ue->mimoInfo.txModDownChgFactor += RG_SCH_MODE_CHNG_STEPUP_FACTOR; + } + else + { + ue->mimoInfo.txModDownChgFactor -= RG_SCH_MODE_CHNG_STEPDOWN_FACTOR; + } + + ue->mimoInfo.txModDownChgFactor = + RGSCH_MAX(ue->mimoInfo.txModDownChgFactor, -(RG_SCH_MODE_CHNG_STEPDOWN_THRSHD)); + + if(ue->mimoInfo.txModDownChgFactor >= RG_SCH_MODE_CHNG_STEPDOWN_THRSHD) + { + /* Trigger Mode step down */ + modTxMode = RGR_UE_TM_3; + rgSCHCmnSendTxModeInd(cell, ue, modTxMode); + } + } + + /* Check for Setup up */ + /* Step Up only when TM3 is configured, Max possible Mode is TM4*/ + if(RGR_UE_TM_3 == txMode) + { + if((previTbs > reportediTbs) || (maxiTbs == previTbs)) + { + ue->mimoInfo.txModUpChgFactor += RG_SCH_MODE_CHNG_STEPUP_FACTOR; + } + else + { + ue->mimoInfo.txModUpChgFactor -= RG_SCH_MODE_CHNG_STEPDOWN_FACTOR; + } + + ue->mimoInfo.txModUpChgFactor = + RGSCH_MAX(ue->mimoInfo.txModUpChgFactor, -(RG_SCH_MODE_CHNG_STEPUP_THRSHD)); + + /* Check if TM step up need to be triggered */ + if(ue->mimoInfo.txModUpChgFactor >= RG_SCH_MODE_CHNG_STEPUP_THRSHD) + { + /* Trigger mode chnage */ + modTxMode = RGR_UE_TM_4; + rgSCHCmnSendTxModeInd(cell, ue, modTxMode); + } + } + + RETVOID; +} +#endif + +/** +* @brief Updates the GBR LCGs when datInd is received from MAC + * + * @details + * + * Function: rgSCHCmnIsDlCsgPrio (cell) + * Purpose: This function returns if csg UEs are + * having priority at current time + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgInfUeDatInd *datInd + * @return Void + **/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnIsDlCsgPrio +( +RgSchCellCb *cell +) +#else +PUBLIC Bool rgSCHCmnIsDlCsgPrio(cell) +RgSchCellCb *cell; +#endif +{ + + RgSchCmnDlCell *cmnDlCell = RG_SCH_CMN_GET_DL_CELL(cell); + + TRC2(rgSCHCmnIsDlCsgPrio) + /* Calculating the percentage resource allocated */ + if(RGR_CELL_ACCS_HYBRID != rgSchCb[cell->instIdx].rgrSchedEnbCfg.accsMode) + { + RETVALUE(FALSE); + } + else + { + if(((cmnDlCell->ncsgPrbCnt * 100) / cmnDlCell->totPrbCnt) < cell->minDlResNonCsg) + { + RETVALUE(FALSE); + } + else + { + RETVALUE(TRUE); + } + } +} + +/** +* @brief Updates the GBR LCGs when datInd is received from MAC + * + * @details + * + * Function: rgSCHCmnIsUlCsgPrio (cell) + * Purpose: This function returns if csg UEs are + * having priority at current time + * + * Invoked by: Scheduler + * + * @param[in] RgSchCellCb *cell + * @param[in] RgSchUeCb *ue + * @param[in] RgInfUeDatInd *datInd + * @return Void + **/ +#ifdef ANSI +PUBLIC Bool rgSCHCmnIsUlCsgPrio +( +RgSchCellCb *cell +) +#else +PUBLIC Bool rgSCHCmnIsUlCsgPrio(cell) +RgSchCellCb *cell; +#endif +{ + RgSchCmnUlCell *cmnUlCell = RG_SCH_CMN_GET_UL_CELL(cell); + + TRC2(rgSCHCmnIsUlCsgPrio) + + /* Calculating the percentage resource allocated */ + if(RGR_CELL_ACCS_HYBRID != rgSchCb[cell->instIdx].rgrSchedEnbCfg.accsMode) + { + RETVALUE(FALSE); + } + else + { + if (((cmnUlCell->ncsgPrbCnt * 100) /cmnUlCell->totPrbCnt) < cell->minUlResNonCsg) + { + RETVALUE(FALSE); + } + else + { + RETVALUE(TRUE); + } + } +} + +/** @brief DL scheduler for SPS, and all other downlink data + * + * @details + * + * Function: rgSchCmnPreDlSch + * + * @param [in] Inst schInst; + * Returns: Void + * + */ +#ifdef ANSI + PUBLIC Void rgSchCmnPreDlSch +( + RgSchCellCb **cell, + U8 nCell, + RgSchCellCb **cellLst + ) +#else +PUBLIC Void rgSchCmnPreDlSch(cell, nCell, cellLst) + RgSchCellCb **cell; + U8 nCell; + RgSchCellCb **cellLst; +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell[0]); + RgSchDlSf *sf; + U8 idx; + + TRC2(rgSchCmnPreDlSch); + + if(nCell > CM_LTE_MAX_CELLS) + { + RETVOID; + } + + if (cell[0]->isDlDataAllwd && (cell[0]->stopDlSch == FALSE)) + { + /* Specific DL scheduler to perform UE scheduling */ + cellSch->apisDl->rgSCHDlPreSched(cell[0]); + + /* Rearranging the cell entries based on their remueCnt in SF. + * cells will be processed in the order of number of ue scheduled + * in that cell */ + for (idx = 0; idx < nCell; idx++) + { + U8 j; + cellSch = RG_SCH_CMN_GET_CELL(cell[idx]); + sf = cellSch->allocInfo.dedAlloc.dedDlSf; + + if(idx == 0) + { + cellLst[idx] = cell[idx]; + continue; + } + + for(j = 0; j < idx; j++) + { + RgSchCmnCell *cmnCell = RG_SCH_CMN_GET_CELL(cellLst[j]); + RgSchDlSf *subfrm = cmnCell->allocInfo.dedAlloc.dedDlSf; + + if(sf->remUeCnt < subfrm->remUeCnt) + { + U8 k; + for(k = idx; k > j; k--) + { + cellLst[k] = cellLst[k-1]; + } + break; + } + } + cellLst[j] = cell[idx]; + } + } + else + { + for (idx = 0; idx < nCell; idx++) + { + cellLst[idx] = cell[idx]; + } + } + RETVOID; +} + +/** @brief DL scheduler for SPS, and all other downlink data + * @details + * + * Function: rgSchCmnPstDlSch + * + * @param [in] Inst schInst; + * Returns: Void + * + */ +#ifdef ANSI +PUBLIC Void rgSchCmnPstDlSch +( + RgSchCellCb *cell +) +#else +PUBLIC Void rgSchCmnPstDlSch(cell) + RgSchCellCb *cell +#endif +{ + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); + + TRC2(rgSchCmnPstDlSch); + + if (cell->isDlDataAllwd && (cell->stopDlSch == FALSE)) + { + cellSch->apisDl->rgSCHDlPstSched(cell->instIdx); + } +} + +#ifdef ANSI +PUBLIC U8 rgSCHCmnCalcPcqiBitSz +( + RgSchUeCb *ueCb, + U8 numTxAnt +) +#else +PUBLIC U8 rgSCHCmnCalcPcqiBitSz(ueCb, numTxAnt) + RgSchUeCb *ueCb; + U8 numTxAnt; +#endif +{ + U8 confRepMode; + U8 pcqiSz; + U8 ri; + RgSchUePCqiCb *cqiCb = ueCb->nPCqiCb; + + TRC3(rgSCHCmnCalcPcqiBitSz); + + confRepMode = cqiCb->cqiCfg.cqiSetup.prdModeEnum; + if((ueCb->mimoInfo.txMode != RGR_UE_TM_3) && + (ueCb->mimoInfo.txMode != RGR_UE_TM_4)) + { + ri =1; + } + else + { + ri = cqiCb->perRiVal; + } + switch(confRepMode) + { + case RGR_PRD_CQI_MOD10: + { + pcqiSz = 4; + } + break; + + case RGR_PRD_CQI_MOD11: + { + if(numTxAnt == 2) + { + if (ri ==1) + { + pcqiSz = 6; + } + else + { + pcqiSz = 8; + } + } + else if(numTxAnt == 4) + { + if (ri ==1) + { + pcqiSz = 8; + } + else + { + pcqiSz = 11; + } + } + else + { + /* This is number of antenna case 1. + * This is not applicable for Mode 1-1. + * So setting it to invalid value */ + pcqiSz = 0; + } + } + break; + + case RGR_PRD_CQI_MOD20: + { + if(cqiCb->isWb) + { + pcqiSz = 4; + } + else + { + pcqiSz = 4 + cqiCb->label; + } + } + break; + + case RGR_PRD_CQI_MOD21: + { + if(cqiCb->isWb) + { + if(numTxAnt == 2) + { + if (ri ==1) + { + pcqiSz = 6; + } + else + { + pcqiSz = 8; + } + } + else if(numTxAnt == 4) + { + if (ri ==1) + { + pcqiSz = 8; + } + else + { + pcqiSz = 11; + } + } + else + { + /* This might be number of antenna case 1. + * For mode 2-1 wideband case only antenna port 2 or 4 is supported. + * So setting invalid value.*/ + pcqiSz = 0; + } + } + else + { + if (ri ==1) + { + pcqiSz = 4 + cqiCb->label; + } + else + { + pcqiSz = 7 + cqiCb->label; + } + } + } + break; + default: + pcqiSz = 0; + break; + } + + RETVALUE(pcqiSz); +} + +/** @brief DL scheduler for SPS, and all other downlink data + * + * @details + * + * Function: rgSCHCmnDlSch + * + * @param [in] RgSchCellCb *cell + * + * Returns: Void + * + */ +#ifdef ANSI +PUBLIC Void rgSCHCmnDlSch +( + RgSchCellCb *cell + ) +#else +PUBLIC Void rgSCHCmnDlSch (cell) + RgSchCellCb *cell; +#endif +{ + RgSchDlSf *dlSf; + RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell); +#ifdef RG_5GTF + RgSchDynTddCb *rgSchDynTddInfo = &(rgSchCb[cell->instIdx].rgSchDynTdd); + U16 dlCntrlSfIdx; +#endif + + TRC2(rgSCHCmnDlSch); + + dlSf = rgSCHUtlSubFrmGet(cell, cellSch->dl.time); +#ifdef RG_5GTF + if (rgSchDynTddInfo->isDynTddEnbld) + { + RG_SCH_DYN_TDD_GET_SFIDX(dlCntrlSfIdx, rgSchDynTddInfo->crntDTddSfIdx, + RG_SCH_CMN_DL_DELTA); + if(RG_SCH_DYNTDD_DLC_ULD == rgSchDynTddInfo->sfInfo[dlCntrlSfIdx].sfType) + { + if(1 == cell->cellId) + { + ul5gtfsidDlAlreadyMarkUl++; + /* + printf("ul5gtfsidDlAlreadyMarkUl: %d, [sfn:sf] [%04d:%02d]\n", + ul5gtfsidDlAlreadyMarkUl, cellSch->dl.time.sfn, + cellSch->dl.time.subframe); + */ + } + RETVOID; + } + } +#endif + + /* Specific DL scheduler to perform UE scheduling */ + cellSch->apisDl->rgSCHDlNewSched(cell, &cellSch->allocInfo); + /* LTE_ADV_FLAG_REMOVED_END */ + + /* call common allocator for RB Allocation */ + rgSCHCmnDlRbAlloc(cell, &cellSch->allocInfo); + + /* Finalize the Allocations for reqested Against alloced */ + rgSCHCmnDlAllocFnlz(cell); + + /* Perform Pdcch allocations for PDCCH Order Q. + * As of now, giving this the least preference. + * This func call could be moved above other allocations + * as per need */ + rgSCHCmnGenPdcchOrder(cell, dlSf); + + /* Do group power control for PUCCH */ + rgSCHCmnGrpPwrCntrlPucch(cell, dlSf); + + RETVOID; +} + +/********************************************************************** + + End of file +**********************************************************************/