JIRA ID: ODUHIGH-381 : DL packets Scheduling as per RRM Policy 62/6862/10
authorlal.harshita <Harshita.Lal@radisys.com>
Tue, 26 Oct 2021 12:45:20 +0000 (18:15 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Thu, 28 Oct 2021 07:47:40 +0000 (13:17 +0530)
Change-Id: I8a04e5a4872a68912a9b0479b7bf8fdf8e315b0e
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
src/5gnrrlc/rlc_utl_dl.c
src/5gnrsch/sch.c
src/5gnrsch/sch.h
src/5gnrsch/sch_common.c
src/5gnrsch/sch_slot_ind.c
src/5gnrsch/sch_ue_mgr.c
src/5gnrsch/sch_utils.c
src/5gnrsch/sch_utils.h
src/cm/common_def.h

index 8722a2e..6e681df 100755 (executable)
@@ -230,14 +230,16 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
    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));
@@ -267,31 +269,31 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
                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 *)&copyLen);
-              dlData->pduInfo[dlData->numPdu].pduLen = pduLen;
+                     dlData->pduInfo[dlData->numPdu].pduBuf, (MsgLen *)&copyLen);
+               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 */
@@ -304,6 +306,42 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
          }/* 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)
       {
@@ -311,11 +349,11 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
          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;
@@ -330,10 +368,10 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
          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;
       }
@@ -353,7 +391,7 @@ uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
       }
    } /* For Data per UE */
    RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo, sizeof(RguDDatReqInfo));
-   
+
    return ROK;
 }/* End of rlcSendDedLcDlData */
 
@@ -389,31 +427,32 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
    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++)
    {
@@ -424,11 +463,11 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
       {
          /* 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) ); 
@@ -445,7 +484,7 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
 #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;
@@ -480,23 +519,9 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
 #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;
@@ -505,7 +530,7 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
 
 #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 */
@@ -525,6 +550,23 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
                }
 #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 =
@@ -547,8 +589,6 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
                   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) ); 
             }
@@ -564,12 +604,7 @@ uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
          }
 #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)
index 5049663..a98832a 100644 (file)
@@ -927,7 +927,7 @@ uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
 {
    uint8_t  lcId = 0;
    uint16_t ueIdx = 0;
-   uint16_t slot;
+   uint16_t slot = 0;
 #ifdef NR_TDD
    uint16_t slotIdx = 0;
 #endif
@@ -957,7 +957,15 @@ uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
          (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)
    {
@@ -993,7 +1001,7 @@ uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
       schDlSlotInfo = NULL;
       return RFAILED;
    }
-   
+
    schDlSlotInfo->dlMsgInfo->crnti = dlBoInfo->crnti;
    schDlSlotInfo->dlMsgInfo->ndi = 1;
    schDlSlotInfo->dlMsgInfo->harqProcNum = 0;
@@ -1355,6 +1363,109 @@ uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
    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
  **********************************************************************/
index 6105f91..3c78a50 100644 (file)
@@ -90,6 +90,12 @@ typedef enum
    WINDOW_EXPIRED
 }RaRspWindowStatus;
 
+typedef enum 
+{
+   SEARCH,
+   CREATE,
+   DELETE
+}ActionTypeLcLL;
 /**
  * @brief
  * Structure holding LTE MAC's General Configuration information.
@@ -175,11 +181,11 @@ typedef struct schLcCtxt
    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;
 
@@ -194,11 +200,11 @@ typedef struct schUlLcCtxt
    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;
 
@@ -217,6 +223,36 @@ typedef struct schUeCfgCb
    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
@@ -232,6 +268,8 @@ typedef struct schUeCb
    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;
 
 /**
@@ -317,11 +355,13 @@ uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcst
 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);
@@ -334,6 +374,11 @@ uint8_t schFillPuschAlloc(SchUeCb *ueCb, SlotTimingInfo pdcchSlotTime, uint32_t
 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
  **********************************************************************/
index 358347d..75a65f7 100644 (file)
@@ -714,10 +714,9 @@ uint16_t schAllocPucchResource(SchCellCb *cell, uint16_t crnti, uint16_t slot)
  *
  * ****************************************************************/
 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;
@@ -781,9 +780,8 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
       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;
@@ -805,7 +803,7 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
 
    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);
 
@@ -1330,6 +1328,238 @@ SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
    }
 }
 
+/*******************************************************************************************
+ *
+ * @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
  **********************************************************************/
index 76a840d..52a3067 100644 (file)
@@ -193,7 +193,7 @@ PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
  *
  * @details
  *
- *    Function : 
+ *    Function : schFillBoGrantDlSchedInfo 
  *
  *    Functionality:
  
@@ -205,11 +205,19 @@ PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
  * ****************************************************************/
 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)
    {
@@ -230,28 +238,54 @@ uint8_t schFillBoGrantDlSchedInfo(SchCellCb *cell, DlSchedInfo *dlSchedInfo, DlM
       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 */
@@ -260,15 +294,73 @@ uint8_t schFillBoGrantDlSchedInfo(SchCellCb *cell, DlSchedInfo *dlSchedInfo, DlM
          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
@@ -277,10 +369,11 @@ uint8_t schFillBoGrantDlSchedInfo(SchCellCb *cell, DlSchedInfo *dlSchedInfo, DlM
        * 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);
 
index 3843546..8be797c 100644 (file)
@@ -172,79 +172,51 @@ void fillSchUlLcCtxt(SchUlLcCtxt *ueCbLcCfg, SchLcCfg *lcCfg)
 
 /*******************************************************************
  *
- * @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;  
 }
 
 /*******************************************************************
@@ -269,6 +241,9 @@ uint8_t fillSchUeCb(SchUeCb *ueCb, SchUeCfg *ueCfg)
    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;
@@ -289,7 +264,7 @@ uint8_t fillSchUeCb(SchUeCb *ueCb, SchUeCfg *ueCfg)
       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);
 
@@ -321,55 +296,130 @@ uint8_t fillSchUeCb(SchUeCb *ueCb, SchUeCfg *ueCfg)
    //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));
@@ -856,6 +906,7 @@ void deleteSchUeCb(SchUeCb *ueCb)
    uint8_t timeDomRsrcIdx = 0, ueLcIdx = 0;
    SchPucchCfg *pucchCfg = NULLP;
    SchPdschConfig *pdschCfg = NULLP;
+   CmLListCp *lcLL  = NULLP;
 
    if(ueCb)
    {
@@ -892,14 +943,32 @@ void deleteSchUeCb(SchUeCb *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));
    }
 }
index fefeff8..668d0c2 100644 (file)
@@ -1319,6 +1319,294 @@ bool fillPrbBitmap(uint64_t *prbBitMap, uint16_t startPrb, uint16_t numPrb)
    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
 
 /**
index 98c3e7e..78a0400 100644 (file)
@@ -33,6 +33,7 @@
 #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) \
 {                                                \
@@ -128,6 +129,14 @@ void removeAllocatedPrbFromFreePrbList(CmLListCp *freePrbBlockList, CmLList *nod
 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
  **********************************************************************/
index a244ee1..89b5d89 100644 (file)
@@ -59,7 +59,7 @@
 #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,