uint16_t pduLen; /* PDU length */
uint16_t copyLen; /* Number of bytes copied */
uint8_t lcId = 0;
+ RlcBoStatus *boStatus = NULLP; /* Buffer occupancy status information */
+ uint8_t ret = ROK;
RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- dlData, sizeof(RlcData));
+ dlData, sizeof(RlcData));
if(dlData == NULLP)
{
DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed for dl data");
RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- datReqInfo, sizeof(RguDDatReqInfo));
+ datReqInfo, sizeof(RguDDatReqInfo));
return RFAILED;
}
memset(dlData, 0, sizeof(RlcData));
dlData->pduInfo[dlData->numPdu].lcId = datPerLch.lcId;
/* Copy Message to fixed buffer to send */
- ODU_GET_MSG_LEN(datPerLch.pdu.mBuf[pduIdx], (MsgLen *)&pduLen);
- RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- dlData->pduInfo[dlData->numPdu].pduBuf, pduLen);
-
- if (dlData->pduInfo[dlData->numPdu].pduBuf == NULLP )
- {
- DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed");
- for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
- {
- RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
- dlData->pduInfo[pduIdx].pduLen);
- }
- RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- dlData, sizeof(RlcData));
- RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- datReqInfo, sizeof(RguDDatReqInfo));
- return RFAILED;
- }
+ ODU_GET_MSG_LEN(datPerLch.pdu.mBuf[pduIdx], (MsgLen *)&pduLen);
+ RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
+ dlData->pduInfo[dlData->numPdu].pduBuf, pduLen);
+
+ if (dlData->pduInfo[dlData->numPdu].pduBuf == NULLP )
+ {
+ DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed");
+ for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
+ {
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlData->pduInfo[pduIdx].pduBuf,\
+ dlData->pduInfo[pduIdx].pduLen);
+ }
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
+ dlData, sizeof(RlcData));
+ RLC_FREE_SHRABL_BUF(post->region, post->pool,
+ datReqInfo, sizeof(RguDDatReqInfo));
+ return RFAILED;
+ }
ODU_COPY_MSG_TO_FIX_BUF(datPerLch.pdu.mBuf[pduIdx], 0, pduLen, \
- dlData->pduInfo[dlData->numPdu].pduBuf, (MsgLen *)©Len);
- dlData->pduInfo[dlData->numPdu].pduLen = pduLen;
+ dlData->pduInfo[dlData->numPdu].pduBuf, (MsgLen *)©Len);
+ dlData->pduInfo[dlData->numPdu].pduLen = pduLen;
/* Free message */
- ODU_PUT_MSG_BUF(datPerLch.pdu.mBuf[pduIdx]);
+ ODU_PUT_MSG_BUF(datPerLch.pdu.mBuf[pduIdx]);
dlData->numPdu++;
}/* For per PDU */
}/* For Data per Lch */
}/* For Data per Tb */
+ /*No Data to send for this UE, Only send the BO REQUEST to SCH */
+ if(dlData->numPdu == 0)
+ {
+ for(lchIdx = 0; lchIdx < dlData->numLc; lchIdx++)
+ {
+ RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, \
+ boStatus, sizeof(RlcBoStatus));
+ if(boStatus == NULLP)
+ {
+ DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed for boStatus");
+ ret = RFAILED;
+ break;
+ }
+ boStatus->cellId = dlData->cellId;
+ GET_UE_IDX(dlData->rnti, boStatus->ueIdx);
+ boStatus->commCh = FALSE;
+ boStatus->lcId = dlData->boStatus[lchIdx].lcId;
+ boStatus->bo = dlData->boStatus[lchIdx].bo;
+
+ FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_BO_STATUS_TO_MAC);
+ /* Send Status Response to MAC layer */
+ if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
+ {
+ DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Failed to send BO status");
+ RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
+ ret = RFAILED;
+ break;
+ }
+ DU_LOG("\nINFO --> RLC_DL : rlcSendDedLcDlData: BO Status sent successfully for LCID:%d,BO:%d",\
+ boStatus->lcId, boStatus->bo);
+ }
+ RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlData, sizeof(RlcData));
+ RLC_FREE_SHRABL_BUF(post->region, post->pool, datReqInfo, sizeof(RguDDatReqInfo));
+ return (ret);
+ }
+
RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
if(dlRrcMsgRsp == NULLP)
{
for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
{
RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
- dlData->pduInfo[pduIdx].pduLen);
+ dlData->pduInfo[pduIdx].pduLen);
}
RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- datReqInfo, sizeof(RguDDatReqInfo));
+ datReqInfo, sizeof(RguDDatReqInfo));
return RFAILED;
}
dlRrcMsgRsp->cellId = dlData->cellId;
for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
{
RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
- dlData->pduInfo[pduIdx].pduLen);
+ dlData->pduInfo[pduIdx].pduLen);
}
RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
- RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo, sizeof(RguDDatReqInfo));
+ RLC_FREE_SHRABL_BUF(post->region, post->pool, datReqInfo, sizeof(RguDDatReqInfo));
RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
return RFAILED;
}
}
} /* For Data per UE */
RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo, sizeof(RguDDatReqInfo));
-
+
return ROK;
}/* End of rlcSendDedLcDlData */
RguDDatReqInfo *datReqInfo; /* Data Request Information */
RlcRguSapCb *rguSap; /* MAC SAP CB */
uint32_t totNumPdu; /* Total number of PDUS */
+ MsgLen len = 0;
RguStaIndTb *staIndTb = NULLP;
RguDatReqTb *datReqTb = NULLP;
RguDStaIndPerUe *staInd = NULLP;
#ifdef LTE_L2_MEAS
uint32_t grantPerLch[RGU_MAX_LC] = {0};
#endif
-/* kw005.201 added support for L2 Measurement */
+ /* kw005.201 added support for L2 Measurement */
#ifdef LTE_L2_MEAS_LOSS_DELAY
uint8_t snIdx1;
uint8_t snIdx2;
#endif /* LTE_L2_MEAS */
uint32_t idx, ueDataIdx = 0;
-//Debug
+ //Debug
uint32_t staIndSz=0,datIndSz = 0;
datReqInfo = NULLP;
RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
- datReqInfo,sizeof(RguDDatReqInfo));
+ datReqInfo,sizeof(RguDDatReqInfo));
#if (ERRCLASS & ERRCLS_ADD_RES)
- if ( datReqInfo == NULLP )
- {
- DU_LOG("\nERROR --> RLC_DL : rlcUtlSendToMac: Memory allocation failed");
- return RFAILED;
- }
+ if ( datReqInfo == NULLP )
+ {
+ DU_LOG("\nERROR --> RLC_DL : rlcUtlSendToMac: Memory allocation failed");
+ return RFAILED;
+ }
#endif /* ERRCLASS & ERRCLS_ADD_RES */
for(idx = 0; idx < staIndInfo->nmbOfUeGrantPerTti; idx++)
{
{
/* Fetch UeCb failed */
DU_LOG("\nERROR --> RLC_DL : rlcUtlSendToMac: UeId[%u]:ueCb not found",
- staInd->rnti);
+ staInd->rnti);
/* If ueCb is not found for current rnti then continue to look for next rnti*/
continue;
}
-
+
/* kw002.201 Removed the allocation of RlcDatReq */
/* kw004.201 Used SSI function to initialize the variable */
memset(&datReq, 0, sizeof(RlcDatReq) );
#ifdef LTE_L2_MEAS
/*Calculate the total grant size from MAC */
if((staIndTb->lchStaInd[count].lcId >= RGU_MAX_LC)
- || (staIndTb->lchStaInd[count].lcId == 0))
+ || (staIndTb->lchStaInd[count].lcId == 0))
{
/* TODO : Need to figure out why this is happening */
break;
#ifdef LTE_L2_MEAS
grantPerLch[staIndTb->lchStaInd[count].lcId] = datReq.totMacGrant;
#endif
- if ( 0 == datReq.pduInfo.numPdu )
- {
- continue;
- }
- totNumPdu += datReq.pduInfo.numPdu;
- memcpy(&(datReqTb->lchData[count].pdu),
- &(datReq.pduInfo),sizeof(KwPduInfo));
-
- for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
- {
- MsgLen len = 0;
- ODU_GET_MSG_LEN(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
- datIndSz += len;
- }
datReqTb->lchData[count].setMaxUlPrio = FALSE;
if (RLC_AM_IS_POLL_BIT_SET(RLC_AMDL) &&
- (RLC_AMDL.sduQ.count > 1))
+ (RLC_AMDL.sduQ.count > 1))
{
/* Poll bit is set indicate to MAC*/
datReqTb->lchData[count].setMaxUlPrio = TRUE;
#ifdef CCPU_OPT
datReqTb->lchData[count].boReport.estRlcHdrSz =
- datReq.boRep.estHdrSz;
+ datReq.boRep.estHdrSz;
datReqTb->lchData[count].boReport.staPduPrsnt =
datReq.boRep.staPduPrsnt;
#endif /* CCPU_OPT */
}
#endif
+ datReqTb->lchData[count].boReport.oldestSduArrTime =
+ datReq.boRep.oldestSduArrTime;
+ if ( 0 == datReq.pduInfo.numPdu )
+ {
+ /* kw004.201 Used SSI function to initialize the variable */
+ memset(&datReq, 0, sizeof(RlcDatReq) );
+ continue;
+ }
+ totNumPdu += datReq.pduInfo.numPdu;
+ memcpy(&(datReqTb->lchData[count].pdu),
+ &(datReq.pduInfo),sizeof(KwPduInfo));
+
+ for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
+ {
+ ODU_GET_MSG_LEN(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
+ datIndSz += len;
+ }
/* kw005.201 added support for L2 Measurement */
#ifdef LTE_L2_MEAS_LOSS_DELAY
datReqTb->rguSnInfo->lchMap[count].lChId =
tbSnMap->prevNumSn = tbSnMap->numSn;
}
#endif
- datReqTb->lchData[count].boReport.oldestSduArrTime =
- datReq.boRep.oldestSduArrTime;
/* kw004.201 Used SSI function to initialize the variable */
memset(&datReq, 0, sizeof(RlcDatReq) );
}
}
#endif
datReqTb->nmbLch = staIndTb->nmbLch;
- /*adding the check to make sure that lcId is not sent as 0
- * when no data is there in datReq */
- if ( 0 == totNumPdu )
- {
- datReqTb->lchData[0].lcId = staIndTb->lchStaInd[0].lcId;
- }
+
/* kw005.201 added support for L2 Measurement */
#ifdef LTE_L2_MEAS_LOSS_DELAY
if(tbSnMap->numSn == 0)
{
uint8_t lcId = 0;
uint16_t ueIdx = 0;
- uint16_t slot;
+ uint16_t slot = 0;
#ifdef NR_TDD
uint16_t slotIdx = 0;
#endif
(lcId >= MIN_DRB_LCID && lcId <= MAX_DRB_LCID))
{
SET_ONE_BIT(ueIdx, cell->boIndBitMap);
- ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
+ if(ueCb->dlInfo.dlLcCtxt[lcId].lcId == lcId)
+ {
+ ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
+ }
+ else
+ {
+ DU_LOG("ERROR --> SCH: LCID:%d is not configured in SCH Cb",lcId);
+ return RFAILED;
+ }
}
else if(lcId != SRB0_LCID)
{
schDlSlotInfo = NULL;
return RFAILED;
}
-
+
schDlSlotInfo->dlMsgInfo->crnti = dlBoInfo->crnti;
schDlSlotInfo->dlMsgInfo->ndi = 1;
schDlSlotInfo->dlMsgInfo->harqProcNum = 0;
return ROK;
}
+/*******************************************************************************
+ *
+ * @brief Try to find Best Free Block with Max Num PRB
+ *
+ * @details
+ *
+ * Function : searchLargestFreeBlockDL
+ *
+ * Functionality:
+ * Finds the FreeBlock with MaxNum of FREE PRB considering SSB/SIB1 ocassions.
+ *
+ * @params[in] I/P > prbAlloc table (FreeBlock list)
+ * I/P > Slot timing Info
+ * O/P > Start PRB
+ *
+ *
+ * @return Max Number of Free PRB
+ * If 0, then no Suitable Free Block
+ *
+ * ********************************************************************************/
+
+uint16_t searchLargestFreeBlockDL(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb)
+{
+ uint16_t broadcastPrbStart=0, broadcastPrbEnd=0, maxFreePRB = 0;
+ PduTxOccsaion ssbOccasion=0, sib1Occasion=0;
+ FreePrbBlock *freePrbBlock = NULLP;
+ CmLList *freePrbNode = NULLP;
+
+ SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
+ SchPrbAlloc *prbAlloc = &schDlSlotInfo->prbAlloc;
+
+ ssbOccasion = schCheckSsbOcc(cell, slotTime);
+ sib1Occasion = schCheckSib1Occ(cell, slotTime);
+
+ if(ssbOccasion && sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+ else if(ssbOccasion)
+ {
+ broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
+ broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
+ }
+ else if(sib1Occasion)
+ {
+ broadcastPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
+ broadcastPrbEnd = broadcastPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
+ }
+
+
+ freePrbNode = prbAlloc->freePrbBlockList.first;
+ *startPrb = 0; /*Initialize the StartPRB to zero*/
+ while(freePrbNode)
+ {
+ freePrbBlock = (FreePrbBlock *)freePrbNode->node;
+
+ /*For block with same numFreeBlocks, choose the one with HighestPRB range
+ *Since FreeBLockList are arranged in Descending order of PRB range thus Skipping this block*/
+ if(maxFreePRB >= freePrbBlock->numFreePrb)
+ {
+ //skip this block
+ freePrbNode = freePrbNode->next;
+ continue;
+ }
+
+ /* If broadcast message is scheduled in this slot, then check if its PRBs belong to the current free block.
+ * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
+ if((ssbOccasion || sib1Occasion) &&
+ ((broadcastPrbStart >= freePrbBlock->startPrb) && (broadcastPrbStart <= freePrbBlock->endPrb)) && \
+ ((broadcastPrbEnd >= freePrbBlock->startPrb) && (broadcastPrbEnd <= freePrbBlock->endPrb)))
+ {
+
+ /* Implmentation is done such that highest-numbered free-RB is Checked first
+ and freePRB in this block is greater than Max till now */
+ if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) > maxFreePRB))
+ {
+ /* If sufficient free PRBs are available above broadcast message*/
+ *startPrb = broadcastPrbEnd + 1;
+ maxFreePRB = (freePrbBlock->endPrb - broadcastPrbEnd);
+ }
+ /*Also check the other freeBlock (i.e. Above the broadcast message) for MAX FREE PRB*/
+ if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) > maxFreePRB))
+ {
+ /* If free PRBs are available below broadcast message*/
+ *startPrb = freePrbBlock->startPrb;
+ maxFreePRB = (broadcastPrbStart - freePrbBlock->startPrb);
+ }
+ }
+ else //Best Block
+ {
+ if(maxFreePRB < freePrbBlock->numFreePrb)
+ {
+ *startPrb = freePrbBlock->startPrb;
+ maxFreePRB = freePrbBlock->numFreePrb;
+ }
+
+ }
+ freePrbNode = freePrbNode->next;
+ }
+ return(maxFreePRB);
+}
+
/**********************************************************************
End of file
**********************************************************************/
WINDOW_EXPIRED
}RaRspWindowStatus;
+typedef enum
+{
+ SEARCH,
+ CREATE,
+ DELETE
+}ActionTypeLcLL;
/**
* @brief
* Structure holding LTE MAC's General Configuration information.
uint32_t bo;
uint16_t pduSessionId; /*Pdu Session Id*/
Snssai *snssai; /*S-NSSAI assoc with LCID*/
+ bool isDedicated; /*Flag containing Dedicated S-NSSAI or not*/
}SchDlLcCtxt;
typedef struct schDlCb
{
- uint8_t numDlLc;
SchDlLcCtxt dlLcCtxt[MAX_NUM_LC];
}SchDlCb;
uint8_t bsd; // bucketSizeDuration
uint16_t pduSessionId; /*Pdu Session Id*/
Snssai *snssai; /*S-NSSAI assoc with LCID*/
+ bool isDedicated; /*Flag containing Dedicated S-NSSAI or not*/
}SchUlLcCtxt;
typedef struct schUlCb
{
- uint8_t numUlLc;
SchUlLcCtxt ulLcCtxt[MAX_NUM_LC];
}SchUlCb;
SchModulationInfo ulModInfo;
}SchUeCfgCb;
+/*Following structures to keep record and estimations of PRB allocated for each
+ * LC taking into consideration the RRM policies*/
+typedef struct lcInfo
+{
+ uint8_t lcId; /*LCID for which BO are getting recorded*/
+ uint32_t reqBO; /*Size of the BO requested/to be allocated for this LC*/
+ uint32_t allocBO; /*TBS/BO Size which is actually allocated*/
+ uint8_t allocPRB; /*PRB count which is allocated based on RRM policy/FreePRB*/
+}LcInfo;
+
+typedef struct dedicatedLCInfo
+{
+ CmLListCp dedLcList; /*Linklist of LC assoc with RRMPolicyMemberList*/
+ uint16_t rsvdDedicatedPRB; /*Number of PRB reserved for this Dedicated S-NSSAI*/
+}DedicatedLCInfo;
+
+typedef struct schLcPrbEstimate
+{
+ /* TODO: For Multiple RRMPolicies, Make DedicatedLcInfo as array/Double Pointer
+ * and have separate DedLCInfo for each RRMPolcyMemberList*/
+ /* Dedicated LC List will be allocated, if any available*/
+ DedicatedLCInfo *dedLcInfo; /*Contain LCInfo per RRMPolicy*/
+
+ CmLListCp defLcList; /*Linklist of LC assoc with Default S-NSSAI(s)*/
+
+ /* SharedPRB number can be used by any LC.
+ * Need to calculate in every Slot based on PRB availability*/
+ uint16_t sharedNumPrb;
+}SchLcPrbEstimate;
+
/**
* @brief
* UE control block
BsrInfo bsrInfo[MAX_NUM_LOGICAL_CHANNEL_GROUPS];
SchUlCb ulInfo;
SchDlCb dlInfo;
+ SchLcPrbEstimate dlLcPrbEst; /*DL PRB Alloc Estimate among different LC*/
+ SchLcPrbEstimate ulLcPrbEst; /*UL PRB Alloc Estimate among different LC*/
}SchUeCb;
/**
void schProcessRaReq(SlotTimingInfo currTime, SchCellCb *cellCb);
uint8_t schFillRar(SchCellCb *cell, SlotTimingInfo rarTime, uint16_t ueIdx, RarAlloc *rarAlloc, uint8_t k0Index);
uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc *msg4Alloc);
-uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
- uint32_t *accumalatedSize, DlMsgAlloc *dlMsgAlloc);
+uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,\
+ uint32_t tbSize, DlMsgAlloc *dlMsgAlloc, uint16_t startPRB);
uint16_t schAccumalateLcBoSize(SchCellCb *cell, uint16_t ueIdx);
uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, uint8_t startSymbol, uint8_t symbolLength, \
uint16_t *startPrb, uint16_t numPrb);
+uint16_t searchLargestFreeBlockDL(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb);
+void updateGrantSizeForBoRpt(CmLListCp *lcLL, DlMsgAlloc *dlMsgAlloc, uint32_t *accumalatedBOSize);
/* UL scheduling related function declarations */
uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst);
uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, uint8_t startSymbol, uint8_t symbolLength, \
uint16_t *startPrb, uint16_t numPrb);
+/*Generic Functions*/
+LcInfo* handleLcLList(CmLListCp *lcLL, uint8_t lcId, ActionTypeLcLL action);
+void prbAllocUsingRRMPolicy(CmLListCp *lcLL, bool dedicatedPRB, uint16_t mcsIdx,uint8_t numSymbols,\
+ uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded);
+
/**********************************************************************
End of file
**********************************************************************/
*
* ****************************************************************/
uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
- uint32_t *accumalatedSize, DlMsgAlloc *dlMsgAlloc)
+ uint32_t tbSize, DlMsgAlloc *dlMsgAlloc, uint16_t startPRB)
{
uint8_t ueIdx;
- uint16_t tbSize = 0;
PdcchCfg *pdcch = NULLP;
PdschCfg *pdsch = NULLP;
BwpCfg *bwp = NULLP;
pdsch->codeword[cwCount].mcsIndex = ueCb.ueCfg.dlModInfo.mcsIndex;
pdsch->codeword[cwCount].mcsTable = ueCb.ueCfg.dlModInfo.mcsTable;
pdsch->codeword[cwCount].rvIndex = 0;
- tbSize = schCalcTbSize(*accumalatedSize + TX_PAYLOAD_HDR_LEN);
- if(tbSize < *accumalatedSize)
- *accumalatedSize = tbSize - TX_PAYLOAD_HDR_LEN;
+
+ tbSize +=TX_PAYLOAD_HDR_LEN;
pdsch->codeword[cwCount].tbSize = tbSize;
}
pdsch->dataScramblingId = cell->cellCfg.phyCellId;
pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
- pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
+ pdsch->pdschFreqAlloc.freqAlloc.startPrb = startPRB; /*Start PRB will be already known*/
pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, ueCb.ueCfg.dlModInfo.mcsIndex, \
pdschCfg.timeDomRsrcAllociList[0].symbolLength);
}
}
+/*******************************************************************************************
+ *
+ * @brief Allocate the PRB using RRM policy
+ *
+ * @details
+ *
+ * Function : prbAllocUsingRRMPolicy
+ *
+ * Functionality:
+ * [Step1]: Traverse each Node in the LC list
+ * [Step2]: Check whether the LC has ZERO requirement then clean this LC
+ * [Step3]: Calcualte the maxPRB for this LC.
+ * a. For Dedicated LC, maxPRB = sum of remainingReservedPRB and
+ * sharedPRB
+ * b. For Default, just SharedPRB count
+ * [Step4]: If the LC is the First one to be allocated for this UE then add
+ * TX_PAYLODN_LEN to reqBO
+ * [Step5]: Calculate the estimate PRB and estimate BO to be allocated
+ * based on reqBO and maxPRB left.
+ * [Step6]: Based on calculated PRB, Update Reserved PRB and Shared PRB counts
+ * [Step7]: Deduce the reqBO based on allocBO and move the LC node to last.
+ * [Step8]: Continue the next loop from List->head
+ *
+ * [Loop Exit]:
+ * [Exit1]: If all the LCs are allocated in list
+ * [Exit2]: If PRBs are exhausted
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ * I/P > IsDedicatedPRB (Flag to indicate that RESERVED PRB to use
+ * I/P > mcsIdx and PDSCH symbols count
+ * I/P & O/P > Shared PRB , reserved PRB Count
+ * I/P & O/P > Total TBS size accumulated
+ * I/P & O/P > isTxPayloadLenAdded : Decision flag to add the TX_PAYLOAD_HDR_LEN
+ *
+ * @return void
+ *
+ * *******************************************************************************************/
+void prbAllocUsingRRMPolicy(CmLListCp *lcLL, bool isDedicatedPRB, uint16_t mcsIdx,uint8_t numSymbols,\
+ uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded)
+{
+ CmLList *node = NULLP;
+ LcInfo *lcNode = NULLP;
+ uint16_t remReservedPRB = 0, estPrb = 0, maxPRB = 0;
+
+ if(lcLL == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH: LcList not present");
+ return;
+ }
+ node = lcLL->first;
+
+ /*Only for Dedicated LcList, Valid value will be assigned to remReservedPRB
+ * For Other LcList, remReservedPRB = 0*/
+ if(reservedPRB != NULLP && isDedicatedPRB == TRUE)
+ {
+ remReservedPRB = *reservedPRB;
+ }
+
+ /*[Step1]*/
+ while(node)
+ {
+#if 0
+ /*For Debugging purpose*/
+ printLcLL(lcLL);
+#endif
+ lcNode = (LcInfo *)node->node;
+
+ /* [Step2]: Below condition will hit in rare case as it has been taken care during the cleaning
+ * process of LCID which was fully allocated. Check is just for safety purpose*/
+ if(lcNode->reqBO == 0 && lcNode->allocBO == 0)
+ {
+ DU_LOG("\nERROR --> SCH: LCID:%d has no requirement, clearing this node",\
+ lcNode->lcId);
+ deleteNodeFromLList(lcLL, node);
+ SCH_FREE(lcNode, sizeof(LcInfo));
+ node = lcLL->first;
+ continue;
+ }
+
+ /*[Exit1]: All LCs are allocated(allocBO = 0 for fully unallocated LC)*/
+ if(lcNode->allocBO != 0)
+ {
+ DU_LOG("\nWARNING --> SCH: All LC are allocated [SharedPRB:%d]",*sharedPRB);
+ return;
+ }
+
+ /*[Exit2]: If PRBs are exhausted*/
+ if(isDedicatedPRB)
+ {
+ /*Loop Exit: All resources exhausted*/
+ if(remReservedPRB == 0 && *sharedPRB == 0)
+ {
+ DU_LOG("\nWARNING --> SCH: Dedicated resources exhausted for LC:%d",lcNode->lcId);
+ return;
+ }
+ }
+ else
+ {
+ /*Loop Exit: All resources exhausted*/
+ if(*sharedPRB == 0)
+ {
+ DU_LOG("\nWARNING --> SCH: Default resources exhausted for LC:%d",lcNode->lcId);
+ return;
+ }
+ }
+
+ /*[Step3]*/
+ maxPRB = remReservedPRB + *sharedPRB;
+
+ /*[Step4]*/
+ if(!(*isTxPayloadLenAdded))
+ {
+ DU_LOG("\nINFO --> SCH: LC:%d is the First node to be allocated which includes TX_PAYLOAD_HDR_LEN",\
+ lcNode->lcId);
+ *isTxPayloadLenAdded = TRUE;
+ lcNode->allocBO = calculateEstimateTBSize((lcNode->reqBO + TX_PAYLOAD_HDR_LEN),\
+ mcsIdx, numSymbols, maxPRB, &estPrb);
+ lcNode->allocBO -=TX_PAYLOAD_HDR_LEN;
+ }
+ else
+ {
+ /*[Step4]*/
+ lcNode->allocBO = calculateEstimateTBSize(lcNode->reqBO,\
+ mcsIdx, numSymbols, maxPRB, &estPrb);
+ }
+
+ /*[Step6]:Re-adjust the reservedPRB pool count and *SharedPRB Count based on
+ * estimated PRB allocated*/
+ if((isDedicatedPRB == TRUE) && (estPrb <= remReservedPRB))
+ {
+ remReservedPRB = remReservedPRB - estPrb;
+ }
+ else /*LC requirement need PRB share from SharedPRB*/
+ {
+ if(*sharedPRB <= (estPrb - remReservedPRB))
+ {
+ DU_LOG("\nINFO --> SCH: SharedPRB is less");
+ *sharedPRB = 0;
+ }
+ else
+ {
+ *sharedPRB = *sharedPRB - (estPrb - remReservedPRB);
+ }
+ remReservedPRB = 0;
+ }
+
+ /*[Step7]*/
+ lcNode->reqBO -= lcNode->allocBO; /*Update the reqBO with remaining bytes unallocated*/
+ lcNode->allocPRB = estPrb;
+ cmLListAdd2Tail(lcLL, cmLListDelFrm(lcLL, node));
+
+ /*[Step8]:Next loop: First LC to be picked from the list
+ * because Allocated Nodes are moved to the last*/
+ node = lcLL->first;
+
+ }
+ return;
+}
+
+/*******************************************************************************************
+ *
+ * @brief Check the LC List and fill the LC and GrantSize to be sent to MAC as
+ * BO Report
+ *
+ * @details
+ *
+ * Function : updateGrantSizeForBoRpt
+ *
+ * Functionality:
+ * Check the LC List and fill the LC and GrantSize to be sent to MAC as
+ * BO Report in dlMsgAlloc Pointer
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ * I/P & O/P > dlMsgAlloc(Pending LC to be added in this context)
+ * I/P & O/P > accumalatedBOSize
+ * @return void
+ *
+ * *******************************************************************************************/
+void updateGrantSizeForBoRpt(CmLListCp *lcLL, DlMsgAlloc *dlMsgAlloc, uint32_t *accumalatedBOSize)
+{
+ CmLList *node = NULLP, *next = NULLP;
+ LcInfo *lcNode = NULLP;
+
+ if(lcLL == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH: LcList not present");
+ return;
+ }
+
+ if(lcLL->count)
+ {
+ node = lcLL->first;
+ }
+ else
+ {
+ /*lcLL is empty*/
+ return;
+ }
+
+ /*Traverse List*/
+ while(node)
+ {
+ next = node->next;
+ lcNode = (LcInfo *)node->node;
+ if(lcNode != NULLP)
+ {
+ DU_LOG("\nINFO --> SCH : LcID:%d, [reqBO, allocBO, allocPRB]:[%d,%d,%d]",\
+ lcNode->lcId, lcNode->reqBO, lcNode->allocBO, lcNode->allocPRB);
+
+ /*Add this LC to dlMsgAlloc so that if this LC gets allocated, BO
+ * report for allocation can be sent to MAC*/
+ dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].lcId = lcNode->lcId;
+ dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes = lcNode->allocBO;
+
+ /*Calculate the Total Payload/BO size allocated*/
+ *accumalatedBOSize += dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes;
+
+ DU_LOG("\nINFO --> SCH: Added in MAC BO report: LCID:%d,reqBO:%d,Idx:%d, TotalBO Size:%d",\
+ lcNode->lcId,lcNode->reqBO, dlMsgAlloc->numLc, *accumalatedBOSize);
+
+ dlMsgAlloc->numLc++;
+ /*The LC has been fully allocated, clean it*/
+ if(lcNode->reqBO == 0)
+ {
+ handleLcLList(lcLL, lcNode->lcId, DELETE);
+ }
+ }
+ node = next;
+ }/*End of while*/
+ return;
+}
+
/**********************************************************************
End of file
**********************************************************************/
*
* @details
*
- * Function :
+ * Function : schFillBoGrantDlSchedInfo
*
* Functionality:
* ****************************************************************/
uint8_t schFillBoGrantDlSchedInfo(SchCellCb *cell, DlSchedInfo *dlSchedInfo, DlMsgAlloc *dlMsgAlloc)
{
- uint8_t ueIdx, lcIdx;
- uint16_t slot;
- uint16_t crnti = 0;
+ uint8_t ueIdx = 0, lcIdx = 0, pdschSymbols = 0;
+ uint16_t slot = 0, startPrb = 0, maxFreePRB = 0;
+ uint16_t crnti = 0, mcsIdx = 0;
uint32_t accumalatedSize = 0;
SchUeCb *ueCb = NULLP;
+ CmLListCp *lcLL = NULLP;
+ SchPdschConfig pdschCfg;
+
+ /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
+ * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
+ * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
+ * else if only Default list is present then first node in this List will add this overhead len*/
+ bool isTxPayloadLenAdded = FALSE;
while(cell->boIndBitMap)
{
dlSchedInfo->dlMsgAlloc = dlMsgAlloc;
dlMsgAlloc->crnti = crnti;
+ pdschCfg = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg;
+ mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
+
+ /*TODO: K0Index must be used instead of 0th Index in
+ * pdschCfg.timeDomRsrcAllociList*/
+ pdschSymbols = pdschCfg.timeDomRsrcAllociList[0].symbolLength;
/* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
memcpy(&dlMsgAlloc->dlMsgInfo, cell->schDlSlotInfo[slot]->dlMsgInfo, \
- sizeof(DlMsgInfo));
+ sizeof(DlMsgInfo));
+ /*Re-Initalization per UE*/
/* scheduled LC data fill */
dlMsgAlloc->numLc = 0;
+ isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
+ accumalatedSize = 0;
+
for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
{
if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
{
- dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].lcId = lcIdx;
-
- /* calculation for BO includse RLC and MAC header size */
- dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes = \
- ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE;
- accumalatedSize += dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes;
- dlMsgAlloc->numLc++;
+ /*Check the LC is Dedicated or default and accordingly LCList will
+ * be used*/
+ if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
+ {
+ lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
+ }
+ else
+ {
+ lcLL = &(ueCb->dlLcPrbEst.defLcList);
+ }
+
+ /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
+ if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
+ (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH : Updation in LC List Failed");
+ /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
+ SCH_FREE(dlMsgAlloc, sizeof(DlMsgAlloc));
+ dlSchedInfo->dlMsgAlloc = NULLP;
+ return RFAILED;
+ }
}
ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
- }
-
- if (!dlMsgAlloc->numLc)
+ }//End of for loop
+
+
+ if ((ueCb->dlLcPrbEst.defLcList.count == 0) && \
+ ((ueCb->dlLcPrbEst.dedLcInfo != NULL) && (ueCb->dlLcPrbEst.dedLcInfo->dedLcList.count == 0)))
{
DU_LOG("\nDEBUG --> SCH : No pending BO for any LC id\n");
/* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
return ROK;
}
- /* pdcch and pdsch data is filled */
- if((schDlRsrcAllocDlMsg(cell, dlSchedInfo->schSlotValue.dlMsgTime, crnti, &accumalatedSize, dlMsgAlloc)) != ROK)
+ /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
+ maxFreePRB = searchLargestFreeBlockDL(cell, dlSchedInfo->schSlotValue.dlMsgTime, &startPrb);
+
+ /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
+ * the list based on RRM policy*/
+
+ /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or
+ * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
+ if(maxFreePRB != 0)
+ {
+ if((ueCb->dlLcPrbEst.dedLcInfo == NULLP)
+ || ((maxFreePRB < ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
+ {
+ ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
+ DU_LOG("\nWARNING --> SCH : Only Default Slice is scheduled, sharedPRB Count:%d",\
+ ueCb->dlLcPrbEst.sharedNumPrb);
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschSymbols,\
+ &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded);
+ }
+ else
+ {
+ ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
+
+ /*PRB Alloc for Dedicated LCs*/
+ prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschSymbols,\
+ &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschSymbols, \
+ &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
+ }
+ }
+
+ /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
+ * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/
+ if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
+ updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dlMsgAlloc, &(accumalatedSize));
+
+ updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dlMsgAlloc, &(accumalatedSize));
+
+ /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
+ if (!accumalatedSize)
+ {
+ if(maxFreePRB == 0)
+ {
+ DU_LOG("\nERROR --> SCH : NO FREE PRB!!");
+ }
+ else
+ {
+ /*Schedule the LC for next slot*/
+ DU_LOG("\nDEBUG --> SCH : No LC has been scheduled");
+ }
+ /*Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
+ * Allocation can be done in next slot*/
+ return ROK;
+ }
+ /*[Step6]: pdcch and pdsch data is filled */
+ if((schDlRsrcAllocDlMsg(cell, dlSchedInfo->schSlotValue.dlMsgTime, \
+ crnti, accumalatedSize, dlMsgAlloc, startPrb)) != ROK)
{
DU_LOG("\nERROR --> SCH : Scheduling of DL dedicated message failed");
/* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
SCH_FREE(dlMsgAlloc, sizeof(DlMsgAlloc));
dlSchedInfo->dlMsgAlloc = NULLP;
return RFAILED;
-
}
/* TODO : Update the scheduling byte report for multiple LC based on QCI
* equally amongst all LC with pending data. This is avoid starving of any
* LC
* */
+#if 0
accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
-
+#endif
/* PUCCH resource */
schAllocPucchResource(cell, dlMsgAlloc->crnti, slot);
/*******************************************************************
*
- * @brief Function to update Sch Ul Lc Cb
+ * @brief Function to update/allocate dedLC Info
*
* @details
*
- * Function : updateSchUlCb
+ * Function : updateDedLcInfo
*
- * Functionality: Function to update SCH Ul Lc Cb
+ * Functionality: Function to fill DLDedLcInfo
*
- * @returns void
+ * @params[arg] snssai pointer,
+ * SchRrmPolicy pointer,
+ * SchLcPrbEstimate pointer , It will be filled
+ * isDedicated pointer,(Address of isDedicated flag in LC Context)
*
- * ****************************************************************/
-
-void updateSchUlCb(uint8_t delIdx, SchUlCb *ulInfo)
-{
- uint8_t lcIdx = 0;
-
- for(lcIdx = delIdx; lcIdx < ulInfo->numUlLc; lcIdx++)
- {
- memcpy(&ulInfo->ulLcCtxt[lcIdx], &ulInfo->ulLcCtxt[lcIdx+1], sizeof(SchUlLcCtxt));
- memset(&ulInfo->ulLcCtxt[lcIdx+1], 0, sizeof(SchUlLcCtxt));
- }
- /*Leakage of Last Index*/
- /*Last index of ulLcCtxt(before deletion) should be void*/
- if(ulInfo->ulLcCtxt[ulInfo->numUlLc].snssai != NULLP)
- {
- DU_LOG("ERROR --> SCH: updateSchUlCb Last index:%d (Before Deletion) memory is leaking",\
- ulInfo->numUlLc);
- SCH_FREE(ulInfo->ulLcCtxt[ulInfo->numUlLc].snssai, sizeof(Snssai));
- }
- else
- {
- DU_LOG("INFO --> SCH: updateSchUlCb Last index:%d (before deletion) memory is freed successfully",\
- ulInfo->numUlLc);
-
- }
-}
-
-/*******************************************************************
- *
- * @brief Function to update SCH Dl Lc Cb
- *
- * @details
- *
- * Function : updateSchDlCb
- *
- * Functionality: Function to update SCH DL Lc Cb
- *
- * @returns void
+ * @return ROK >> This LC is part of RRM MemberList.
+ * RFAILED >> FATAL Error
+ * ROKIGNORE >> This LC is not part of this RRM MemberList
*
* ****************************************************************/
-void updateSchDlCb(uint8_t delIdx, SchDlCb *dlInfo)
+uint8_t updateDedLcInfo(Snssai *snssai, SchRrmPolicy *rrmPolicy, SchLcPrbEstimate *lcPrbEst,\
+ bool *isDedicated)
{
- uint8_t lcIdx = 0;
-
- for(lcIdx = delIdx; lcIdx < dlInfo->numDlLc; lcIdx++)
+ if(memcmp(snssai, &(rrmPolicy->memberList.snssai), sizeof(Snssai)))
{
- memcpy(&dlInfo->dlLcCtxt[lcIdx], &dlInfo->dlLcCtxt[lcIdx+1], sizeof(SchDlLcCtxt));
- memset(&dlInfo->dlLcCtxt[lcIdx+1], 0, sizeof(SchDlLcCtxt));
- }
- /*Leakage of Last Index*/
- /*Last index of ulLcCtxt(before deletion) should be void*/
- if(dlInfo->dlLcCtxt[dlInfo->numDlLc].snssai != NULLP)
- {
- DU_LOG("ERROR --> SCH: updateSchDlCb Last index:%d (before deletion) memory is leaking: Delete the S-NSSAI memory",\
- dlInfo->numDlLc);
- SCH_FREE(dlInfo->dlLcCtxt[dlInfo->numDlLc].snssai, sizeof(Snssai));
+ if(lcPrbEst->dedLcInfo == NULLP)
+ {
+ SCH_ALLOC(lcPrbEst->dedLcInfo, sizeof(DedicatedLCInfo));
+ if(lcPrbEst->dedLcInfo == NULLP)
+ {
+ DU_LOG("\nINFO --> SCH : Memory Allocation Failed");
+ return RFAILED;
+ }
+ }
+ /*Updating latest RrmPolicy*/
+ lcPrbEst->dedLcInfo->rsvdDedicatedPRB = \
+ (uint16_t)(((rrmPolicy->policyDedicatedRatio)*(MAX_NUM_RB))/100);
+ *isDedicated = TRUE;
+ DU_LOG("\nINFO --> SCH : Updated RRM policy, reservedPOOL:%d",lcPrbEst->dedLcInfo->rsvdDedicatedPRB);
}
+ /*else case: This LcCtxt is either a Default LC or this LC is part of someother RRM_MemberList*/
else
{
- DU_LOG("INFO --> SCH: updateSchDlCb Last index:%d (before deletion) memory is freed successfully",\
- dlInfo->numDlLc);
+ DU_LOG("\nINFO --> SCH : This SNSSAI is not a part of this RRMPolicy");
}
+ return ROK;
}
/*******************************************************************
uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
SchPdschCfgCmn pdschCfg;
SchPucchDlDataToUlAck *dlDataToUlAck;
+ CmLListCp *lcLL = NULLP;
+ uint8_t retDL = ROK, retUL = ROK;
+ bool isLcIdValid = FALSE;
ueCb->ueCfg.cellId = ueCfg->cellId;
ueCb->ueCfg.crnti = ueCfg->crnti;
memcpy(&ueCb->ueCfg.spCellCfg , &ueCfg->spCellCfg, sizeof(SchSpCellCfg));
covertFreqDomRsrcMapToIAPIFormat(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdcchCfg.cRSetToAddModList[0].freqDomainRsrc,\
- freqDomainResource);
+ freqDomainResource);
memset(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdcchCfg.cRSetToAddModList[0].freqDomainRsrc, 0, FREQ_DOM_RSRC_SIZE);
memcpy(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdcchCfg.cRSetToAddModList[0].freqDomainRsrc, freqDomainResource, FREQ_DOM_RSRC_SIZE);
//Updating SchUlCb and SchDlCb DB in SchUeCb
for(lcIdx = 0; lcIdx < ueCfg->numLcs; lcIdx++)
{
+ isLcIdValid = FALSE; /*Re-Initializing*/
+
+ ueLcIdx = ueCfg->schLcCfg[lcIdx].lcId;
+ CHECK_LCID(ueLcIdx, isLcIdValid);
+ if(isLcIdValid == FALSE)
+ {
+ DU_LOG("ERROR --> SCH: LCID:%d is not Valid",ueLcIdx);
+ continue;
+ }
if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_ADD)
{
- fillSchUlLcCtxt(&ueCb->ulInfo.ulLcCtxt[ueCb->ulInfo.numUlLc], &ueCfg->schLcCfg[lcIdx]);
- ueCb->ulInfo.numUlLc++;
- fillSchDlLcCtxt(&ueCb->dlInfo.dlLcCtxt[ueCb->dlInfo.numDlLc], &ueCfg->schLcCfg[lcIdx]);
- ueCb->dlInfo.numDlLc++;
+ fillSchUlLcCtxt(&ueCb->ulInfo.ulLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
+ fillSchDlLcCtxt(&ueCb->dlInfo.dlLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
+
+ /*Checking whether this LC belong to Dedicated S-NSSAI
+ * and Create the Dedicated LC List & Update the Reserve PRB number*/
+ if(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai != NULLP)
+ {
+ retDL = updateDedLcInfo(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, \
+ ueCb->cellCb->cellCfg.rrmPolicy, &(ueCb->dlLcPrbEst),\
+ &(ueCb->dlInfo.dlLcCtxt[ueLcIdx].isDedicated));
+ }
+ if(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai != NULLP)
+ {
+ retUL = updateDedLcInfo(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai, \
+ ueCb->cellCb->cellCfg.rrmPolicy, &(ueCb->ulLcPrbEst),\
+ &(ueCb->ulInfo.ulLcCtxt[ueLcIdx].isDedicated));
+ }
+
+ if(retUL == RFAILED || retDL == RFAILED)/*FATAL error*/
+ {
+ DU_LOG("\nERROR --> SCH : Failure in updateDedLcInfo");
+ return RFAILED;
+ }
}
else
{
- for(ueLcIdx = 0; ueLcIdx < ueCb->ulInfo.numUlLc; ueLcIdx++) //searching for Lc to be Mod
+ if(ueCb->ulInfo.ulLcCtxt[ueLcIdx].lcId == ueCfg->schLcCfg[lcIdx].lcId)
{
- if(ueCb->ulInfo.ulLcCtxt[ueLcIdx].lcId == ueCfg->schLcCfg[lcIdx].lcId)
+ if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_MOD)
{
- if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_MOD)
+ fillSchUlLcCtxt(&ueCb->ulInfo.ulLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
+ /*Updating the RRM reserved pool PRB count*/
+ if(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai != NULLP)
{
- fillSchUlLcCtxt(&ueCb->ulInfo.ulLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
- break;
+ retUL = updateDedLcInfo(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai, \
+ ueCb->cellCb->cellCfg.rrmPolicy, &(ueCb->ulLcPrbEst),\
+ &(ueCb->ulInfo.ulLcCtxt[ueLcIdx].isDedicated));
}
- /*BUG: ueCfg using lcIdx (Looping around numLCs in ueCfg whereas
- * ueLcIdx Loops around numUlLc in SCH UL DB*/
- if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_DEL)
+ if(retUL == RFAILED)
{
- memset(&ueCb->ulInfo.ulLcCtxt[ueLcIdx], 0, sizeof(SchUlLcCtxt));
- ueCb->ulInfo.numUlLc--;
- updateSchUlCb(ueLcIdx, &ueCb->ulInfo); //moving arr elements one idx ahead
-
- break;
+ DU_LOG("\nERROR --> SCH : Failed in updating Ded Lc info");
+ return RFAILED;
}
}
- }/*End of inner for loop */
+ if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_DEL)
+ {
+ /*Delete the LC node from the UL LC List*/
+ if(ueCb->ulInfo.ulLcCtxt[ueLcIdx].isDedicated)
+ {
+ if(ueCb->ulLcPrbEst.dedLcInfo != NULLP)
+ {
+ lcLL = &(ueCb->ulLcPrbEst.dedLcInfo->dedLcList);
+ handleLcLList(lcLL, ueCfg->schLcCfg[lcIdx].lcId, DELETE);
+ if(lcLL->count == 0)/*IF No Node in DedicateLCList to be deleted*/
+ {
+ /*Free the Dedicated LC Info structure*/
+ SCH_FREE(ueCb->ulLcPrbEst.dedLcInfo, sizeof(DedicatedLCInfo));
+ }
+ }
+ }
+ else/*Default LC list*/
+ {
+ lcLL = &(ueCb->ulLcPrbEst.defLcList);
+ handleLcLList(lcLL, ueCfg->schLcCfg[lcIdx].lcId, DELETE);
+ }
+ SCH_FREE(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai, sizeof(Snssai));
+ memset(&ueCb->ulInfo.ulLcCtxt[ueLcIdx], 0, sizeof(SchUlLcCtxt));
+ }
+ }/*End of UL LC Ctxt*/
- for(ueLcIdx = 0; ueLcIdx < ueCb->dlInfo.numDlLc; ueLcIdx++) //searching for Lc to be Mod
+ if(ueCb->dlInfo.dlLcCtxt[ueLcIdx].lcId == ueCfg->schLcCfg[lcIdx].lcId)
{
- if(ueCb->dlInfo.dlLcCtxt[ueLcIdx].lcId == ueCfg->schLcCfg[lcIdx].lcId)
+ if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_MOD)
+ {
+ fillSchDlLcCtxt(&ueCb->dlInfo.dlLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
+ /*Updating the RRM policy*/
+ if(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai != NULLP)
+ {
+ retDL = updateDedLcInfo(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, \
+ ueCb->cellCb->cellCfg.rrmPolicy, &(ueCb->dlLcPrbEst), \
+ &(ueCb->dlInfo.dlLcCtxt[ueLcIdx].isDedicated));
+ }
+ if(retDL == RFAILED)
+ {
+ DU_LOG("\nERROR --> SCH : Failed in updating Ded Lc info");
+ return RFAILED;
+ }
+ }
+ if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_DEL)
{
- if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_MOD)
+ /*Delete the LC node from the DL LC List*/
+ if(ueCb->dlInfo.dlLcCtxt[ueLcIdx].isDedicated)
{
- fillSchDlLcCtxt(&ueCb->dlInfo.dlLcCtxt[ueLcIdx], &ueCfg->schLcCfg[lcIdx]);
- break;
+ if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
+ {
+ lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
+ handleLcLList(lcLL, ueCfg->schLcCfg[lcIdx].lcId, DELETE);
+ if(lcLL->count == 0)/*Last Node in DedicateLCList to be deleted*/
+ {
+ /*Free the Dedicated LC Info structure*/
+ SCH_FREE(ueCb->dlLcPrbEst.dedLcInfo, sizeof(DedicatedLCInfo));
+ }
+ }
}
- if(ueCfg->schLcCfg[lcIdx].configType == CONFIG_DEL)
+ else
{
- memset(&ueCb->dlInfo.dlLcCtxt[ueLcIdx], 0, sizeof(SchDlLcCtxt));
- ueCb->dlInfo.numDlLc--;
- updateSchDlCb(ueLcIdx, &ueCb->dlInfo); //moving arr elements one idx ahead
- break;
+ lcLL = &(ueCb->dlLcPrbEst.defLcList);
+ handleLcLList(lcLL, ueCfg->schLcCfg[lcIdx].lcId, DELETE);
}
+ SCH_FREE(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, sizeof(Snssai));
+ memset(&ueCb->dlInfo.dlLcCtxt[ueLcIdx], 0, sizeof(SchDlLcCtxt));
}
- }/*End of inner for loop */
+ }/*End of DL LC ctxt*/
}
SCH_FREE(ueCfg->schLcCfg[lcIdx].drbQos, sizeof(SchDrbQosInfo));
uint8_t timeDomRsrcIdx = 0, ueLcIdx = 0;
SchPucchCfg *pucchCfg = NULLP;
SchPdschConfig *pdschCfg = NULLP;
+ CmLListCp *lcLL = NULLP;
if(ueCb)
{
deleteSchPdschServCellCfg(&ueCb->ueCfg.spCellCfg.servCellCfg.pdschServCellCfg);
}
/*Need to Free the memory allocated for S-NSSAI*/
- for(ueLcIdx = 0; ueLcIdx < ueCb->ulInfo.numUlLc; ueLcIdx++)
+ for(ueLcIdx = 0; ueLcIdx < MAX_NUM_LC; ueLcIdx++)
{
SCH_FREE(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai, sizeof(Snssai));
+ SCH_FREE(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, sizeof(Snssai));
}
- for(ueLcIdx = 0; ueLcIdx < ueCb->dlInfo.numDlLc; ueLcIdx++)
+
+ /*Clearing out Dedicated LC list*/
+ if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
{
- SCH_FREE(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, sizeof(Snssai));
+ lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
+ deleteLcLL(lcLL);
+ SCH_FREE(ueCb->dlLcPrbEst.dedLcInfo, sizeof(DedicatedLCInfo));
}
+ if(ueCb->ulLcPrbEst.dedLcInfo != NULLP)
+ {
+ lcLL = &(ueCb->ulLcPrbEst.dedLcInfo->dedLcList);
+ deleteLcLL(lcLL);
+ SCH_FREE(ueCb->ulLcPrbEst.dedLcInfo, sizeof(DedicatedLCInfo));
+ }
+ /*Deleteing the Default LC list*/
+ lcLL = &(ueCb->dlLcPrbEst.defLcList);
+ deleteLcLL(lcLL);
+
+ lcLL = &(ueCb->ulLcPrbEst.defLcList);
+ deleteLcLL(lcLL);
+
memset(ueCb, 0, sizeof(SchUeCb));
}
}
return ROK;
}
+
+/**************************************************************************
+ *
+ * @brief Update the LCID Node in LCLL as per ActionType
+ *
+ * @details
+ *
+ * Function : handleLcLList
+ *
+ * Functionality:
+ * Search LCID in LCLL or if not found, create,Delete, or return
+ * node for this LCID
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ * I/P > lcId
+ * I/P > ActionType (Create,Delete or Just search)
+ *
+ * @return lcNode > Pointer to the Node for that LcInfo
+ * If NULLP, FATAL FAILURE
+ *
+ * ***********************************************************************/
+LcInfo* handleLcLList(CmLListCp *lcLL, uint8_t lcId, ActionTypeLcLL action)
+{
+ CmLList *node = NULLP;
+ LcInfo *lcNode = NULLP;
+ bool found = FALSE;
+
+ if(lcLL == NULLP)
+ {
+ DU_LOG("\nERROR -->SCH: LcList doesnt exist");
+ return NULLP;
+ }
+ node = lcLL->first;
+
+ /*Traversing the LC LinkList*/
+ while(node)
+ {
+ lcNode = (LcInfo *)node->node;
+ if(lcNode->lcId == lcId)
+ {
+ DU_LOG("\nINFO --> SCH : LcID:%d found in LL",lcId);
+ found = TRUE;
+ break;
+ }
+ node = node->next;
+ }//end of while
+
+ switch(action)
+ {
+ case SEARCH:
+ {
+ if(!found)
+ {
+ lcNode = NULLP;
+ }
+ return lcNode;
+ }
+
+ case CREATE:
+ {
+ if(node != NULLP)
+ return lcNode;
+
+ /*Need to add a new node for this LC*/
+
+ /*List is empty; Initialize the LL ControlPointer*/
+ if(lcLL->count == 0)
+ {
+ DU_LOG("\nINFO --> SCH: First LC:%d to add in this List",lcId);
+ cmLListInit(lcLL);
+ }
+
+ lcNode = NULLP;
+ /*Allocate the List*/
+ SCH_ALLOC(lcNode, sizeof(LcInfo));
+ if(lcNode)
+ {
+ lcNode->lcId = lcId;
+ lcNode->reqBO = 0;
+ lcNode->allocBO = 0;
+ lcNode->allocPRB = 0;
+ }
+ else
+ {
+ DU_LOG("\nERROR --> SCH : Allocation of List failed,lcId:%d",lcId);
+ return NULLP;
+ }
+
+ if(addNodeToLList(lcLL, lcNode, NULLP) == RFAILED)
+ {
+ DU_LOG("\nERROR --> SCH : failed to Add Node,lcId:%d",lcId);
+ SCH_FREE(lcNode, sizeof(LcInfo));
+ return NULLP;
+ }
+ DU_LOG("\nINFO --> SCH : Added new Node in List for lcId:%d\n",lcId);
+ return lcNode;
+ }
+
+ case DELETE:
+ {
+ if(!found || lcNode == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH: LCID: %d not found; thus Deletion unsuccessful",lcId);
+ }
+ else
+ {
+ if(deleteNodeFromLList(lcLL, node) == ROK)
+ SCH_FREE(lcNode, sizeof(LcInfo));
+
+ DU_LOG("\nINFO --> SCH: LCID: %d Deleted successfully",lcId);
+ }
+ return NULLP;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> SCH: Action type wrong: %d",action);
+ break;
+ }
+ }
+ return lcNode;
+}
+
+/**************************************************************************
+ *
+ * @brief Update ReqPRB for a partiular LCID in LC Linklist
+ *
+ * @details
+ *
+ * Function : updateLcListReqPRB
+ *
+ * Functionality:
+ * Update ReqPRB for a partiular LCID in LC Linklist
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ * I/P > lcId
+ * I/P > reqPRB
+ * I/P > payloadSize
+ *
+ * @return ROK/RFAILED
+ *
+ * ***********************************************************************/
+uint8_t updateLcListReqPRB(CmLListCp *lcLL, uint8_t lcId, uint32_t payloadSize)
+{
+ LcInfo *lcNode = NULLP;
+
+ lcNode = handleLcLList(lcLL, lcId, CREATE);
+
+ if(lcNode == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH : LC is neither present nor able to create in List lcId:%d",lcId);
+ return RFAILED;
+ }
+ lcNode->reqBO = payloadSize;
+ lcNode->allocBO = 0;
+ lcNode->allocPRB = 0; /*Re-Initializing the AllocPRB*/
+ DU_LOG("\nINFO --> SCH : LCID:%d, reqBO:%d", lcId, lcNode->reqBO);
+ return ROK;
+}
+
+/**************************************************************************
+ *
+ * @brief Delete entire LC Linklist
+ *
+ * @details
+ *
+ * Function : deleteLcLL
+ *
+ * Functionality:
+ * Delete entire LC Linklist
+ *
+ * @params[in] lcLinkList pointer (LcInfo list)
+ *
+ * @return void
+ *
+ * ***********************************************************************/
+void deleteLcLL(CmLListCp *lcLL)
+{
+ CmLList *node = NULLP, *next = NULLP;
+ LcInfo *lcNode = NULLP;
+
+ if(lcLL == NULLP)
+ {
+ DU_LOG("\nINFO --> SCH: LcList doesnt exist");
+ return;
+ }
+ node = lcLL->first;
+
+ while(node)
+ {
+ next = node->next;
+ lcNode = (LcInfo *)node->node;
+ if(deleteNodeFromLList(lcLL, node) == ROK)
+ SCH_FREE(lcNode, sizeof(LcInfo));
+ node = next;
+ }
+}
+
+/****************************************************************************
+ *
+ * @brief Calculate the Estimated TBS Size based on Spec 38.421 , Sec 5.3.1.2
+ *
+ * @details
+ *
+ * Function : calculateEstimateTBSize
+ *
+ * Functionality:
+ * TBS Size calculation requires numPRB. Since exactPRB for reqBO is unknown thus
+ * will give the PRB value(from 0 to maxRB) one by one and
+ * try to find the TBS size closest to reqBO
+ *
+ * @params[in] I/P > reqBO, mcsIdx, num PDSCH symbols,
+ * I/P > maxRB: Maximum PRB count to reach for calculating the TBS
+ * O/P > estPrb : Suitable PRB count for reaching the correct TBS
+ *
+ *
+ * @return TBS Size > Size which will can be allocated for this LC
+ *
+ *
+ *************************************************************************/
+uint32_t calculateEstimateTBSize(uint32_t reqBO, uint16_t mcsIdx,uint8_t numSymbols,\
+ uint16_t maxPRB, uint16_t *estPrb)
+{
+ uint32_t tbs = 0, effecBO = 0;
+
+ *estPrb = MIN_PRB;
+ /*Loop Exit: Either estPRB reaches the maxRB or TBS is found greater than equal to reqBO*/
+ do
+ {
+ tbs = schCalcTbSizeFromNPrb(*estPrb, mcsIdx, numSymbols);
+
+ /*TBS size calculated in above function is in Bits.
+ * So to convert it into Bytes , we right shift by 3.
+ * Eg: tbs=128 bits(1000 0000) ; Right Shift by 3: Tbs = 0001 0000(16 bytes)*/
+ tbs = tbs >> 3;
+ *estPrb += 1;
+ }while((tbs < reqBO) && (*estPrb < maxPRB));
+
+ /*Effective BO is the Grant which can be provided for this LC.
+ * Here,it is decided based on whether we can fully cater its requirment (reqBO)
+ * or has to provide lesser grant due to resource limitation.
+ * Thus effective BO/Grant for this LC will be min of TBS calculated and reqBO*/
+ effecBO = MIN(tbs,reqBO);
+ return (effecBO);
+}
+/*Below function for printing will be used in future so disabling it for now*/
+#if 0
+/****************************************************************************
+ *
+ * @brief Print the LC in list for debugging purpose
+ *
+ * @details
+ *
+ * Function : printLcLL
+ *
+ * Functionality:
+ * For debugging purpose, for printing the LC in the order and
+ * parameters
+ *
+ * @params[in] LcList pointer
+ *
+ * @return void
+ *
+ *************************************************************************/
+void printLcLL(CmLListCp *lcLL)
+{
+ CmLList *node = NULLP;
+ LcInfo *lcNode = NULLP;
+
+ if(lcLL == NULLP)
+ {
+ DU_LOG("\nINFO -->SCH: LcList doesnt exist");
+ return;
+ }
+ node = lcLL->first;
+ while(node)
+ {
+ lcNode = (LcInfo *)node->node;
+ if(lcNode)
+ {
+ DU_LOG("\nINFO --> SCH : LcID:%d, [reqBO, allocBO, allocPRB]:[%d,%d,%d]",\
+ lcNode->lcId,lcNode->reqBO, lcNode->allocBO, lcNode->allocPRB);
+ }
+
+ node = node->next;
+ }
+}
+#endif
+
#ifdef NR_TDD
/**
#define TOTAL_TBSIZE_VALUES 93
#define DEFAULT_UL_ACK_LIST_COUNT 8 /* Max number of pusch time domain uplink allocation */
#define MASK_BIT64_ON 0xFFFFFFFFFFFFFFFF
+#define MIN_PRB 1
#define SET_BITS_MSB(_startBit, _numBits, _byte) \
{ \
uint8_t findDmrsStartSymbol(uint16_t dlDmrsSymbBitMap);
void covertFreqDomRsrcMapToIAPIFormat(uint8_t *sourceBitMap, uint8_t *destBitMap);
+uint8_t updateLcListReqPRB(CmLListCp *lcLL, uint8_t lcId, uint32_t payloadSize);
+uint32_t calculateEstimateTBSize(uint32_t reqBO, uint16_t mcsIdx,uint8_t numSymbols,\
+ uint16_t maxPRB, uint16_t *estPrb);
+void deleteLcLL(CmLListCp *lcLL);
+#if 0
+/*Will be enabled for debugging*/
+void printLcLL(CmLListCp *lcLL);
+#endif
/**********************************************************************
End of file
**********************************************************************/
#define MAX_NUM_MU 4
#define MAX_NUM_UE 2
#define MAX_NUM_UE_PER_TTI 1
-#define MAX_NUM_LC 32 /*Spec 38.331: Sec 6.4: maxLC-ID Keyword*/
+#define MAX_NUM_LC MAX_DRB_LCID + 1 /*Spec 38.331: Sec 6.4: maxLC-ID Keyword*/
#define MAX_NUM_SRB 3 /* Max. no of Srbs */
#define MAX_NUM_DRB 29 /* spec 38.331, maxDRB */
_isCrntiValid = ((_crnti >= ODU_START_CRNTI && _crnti <= ODU_END_CRNTI ) ? 1 : 0); \
}
+#define CHECK_LCID(_lcId, _isLcidValid) \
+{\
+ _isLcidValid = ((_lcId >= SRB0_LCID && _lcId <= MAX_DRB_LCID) ? 1 : 0);\
+}
+
typedef enum
{
UE_CFG_INACTIVE,