Changes for Multi-UE support and DL_MSG scheduling using K0 and K1 [Issue-ID: ODUHIGH...
[o-du/l2.git] / src / 5gnrsch / sch.c
index 5049663..090d389 100644 (file)
@@ -664,6 +664,7 @@ uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg)
    cell->firstSsbTransmitted = false;
    cell->firstSib1Transmitted = false;
    fillSsbStartSymb(cell);
+   cmLListInit(&cell->ueToBeScheduled);
    schCb[inst].cells[inst] = cell;
 
    DU_LOG("\nINFO  -->  SCH : Cell init completed for cellId:%d", cell->cellId);
@@ -926,21 +927,18 @@ uint8_t SchHdlCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
 uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
 {
    uint8_t  lcId = 0;
-   uint16_t ueIdx = 0;
-   uint16_t slot;
-#ifdef NR_TDD
-   uint16_t slotIdx = 0;
-#endif
+   uint16_t ueId = 0;
+   bool isLcIdValid = false;
    SchUeCb *ueCb = NULLP;
    SchCellCb *cell = NULLP;
-   SchDlSlotInfo *schDlSlotInfo = NULLP;
    Inst  inst = pst->dstInst-SCH_INST_START;
+   CmLListCp *lcLL = NULLP;
 
 #ifdef CALL_FLOW_DEBUG_LOG
    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_RLC_BO_INFO_TO_SCH\n");
 #endif
 
-   DU_LOG("\nDEBUG  -->  SCH : Received RLC BO Status indication");
+   DU_LOG("\nDEBUG  -->  SCH : Received RLC BO Status indication LCId [%d] BO [%d]", dlBoInfo->lcId, dlBoInfo->dataVolume);
    cell = schCb[inst].cells[inst];
 
    if(cell == NULLP)
@@ -949,64 +947,59 @@ uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
       return RFAILED;
    }
 
-   GET_UE_IDX(dlBoInfo->crnti, ueIdx);
-   ueCb = &cell->ueCb[ueIdx-1];
+   GET_UE_IDX(dlBoInfo->crnti, ueId);
+   ueCb = &cell->ueCb[ueId-1];
    lcId  = dlBoInfo->lcId;
-
-   if(lcId == SRB1_LCID || lcId == SRB2_LCID || lcId == SRB3_LCID || \
-         (lcId >= MIN_DRB_LCID && lcId <= MAX_DRB_LCID))
+   CHECK_LCID(lcId, isLcIdValid);
+   if(isLcIdValid == FALSE)
    {
-      SET_ONE_BIT(ueIdx, cell->boIndBitMap);
-      ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
-   }
-   else if(lcId != SRB0_LCID)
-   {
-      DU_LOG("\nERROR  -->  SCH : Invalid LC Id %d in MacSchDlRlcBoInfo", lcId);
+      DU_LOG("ERROR --> SCH: LCID:%d is not valid", lcId);
       return RFAILED;
    }
 
-   slot = (cell->slotInfo.slot + SCHED_DELTA + PHY_DELTA_DL + BO_DELTA) % cell->numSlots;
-#ifdef NR_TDD
-   while(schGetSlotSymbFrmt(cell->slotFrmtBitMap, slot) != DL_SLOT)
+   /*Expected when theres a case of Retransmission Failure or Resetablishment
+    *By Zero BO, the RLC is informing that previous data can be cleared out
+    *Thus clearing out the LC from the Lc priority list*/
+   if(dlBoInfo->dataVolume == 0)
    {
-      slot = (slot + 1)%cell->numSlots;
-      slotIdx++;
-      if(slotIdx==cell->numSlots)
+      /*Check the LC is Dedicated or default and accordingly LCList will
+       * be used*/
+      if(ueCb->dlInfo.dlLcCtxt[lcId].isDedicated)
       {
-         DU_LOG("\nERROR  -->  SCH : No DL Slot available");
-         return RFAILED;
+         lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
       }
+      else
+      {
+         lcLL = &(ueCb->dlLcPrbEst.defLcList);
+      }
+      handleLcLList(lcLL, lcId, DELETE);
+      return ROK;
    }
-#endif
-
-   schDlSlotInfo = cell->schDlSlotInfo[slot];
 
-   if(schDlSlotInfo == NULLP)
+   if(lcId == SRB0_LCID)
    {
-      DU_LOG("\nERROR  -->  SCH : MacSchDlRlcBoInfo(): schDlSlotInfo does not exists");
-      return RFAILED;
+      cell->raCb[ueId -1].msg4recvd = true;
+      cell->raCb[ueId -1].dlMsgPduLen = dlBoInfo->dataVolume;
+      
    }
-   SCH_ALLOC(schDlSlotInfo->dlMsgInfo, sizeof(DlMsgInfo));
-   if(schDlSlotInfo->dlMsgInfo == NULLP)
+   else
    {
-      DU_LOG("\nERROR  -->  SCH : Memory allocation failed for dlMsgInfo");
-      schDlSlotInfo = NULL;
-      return RFAILED;
+      /* TODO : These part of changes will be corrected during DL scheduling as
+       * per K0 - K1 -K2 */
+      SET_ONE_BIT(ueId, cell->boIndBitMap);
+      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;
+      }
    }
    
-   schDlSlotInfo->dlMsgInfo->crnti = dlBoInfo->crnti;
-   schDlSlotInfo->dlMsgInfo->ndi = 1;
-   schDlSlotInfo->dlMsgInfo->harqProcNum = 0;
-   schDlSlotInfo->dlMsgInfo->dlAssignIdx = 0;
-   schDlSlotInfo->dlMsgInfo->pucchTpc = 0;
-   schDlSlotInfo->dlMsgInfo->pucchResInd = 0;
-   schDlSlotInfo->dlMsgInfo->harqFeedbackInd = 0;
-   schDlSlotInfo->dlMsgInfo->dciFormatId = 1;
-   if(lcId == SRB0_LCID)
-   {
-      schDlSlotInfo->dlMsgInfo->isMsg4Pdu = true;
-      schDlSlotInfo->dlMsgInfo->dlMsgPduLen = dlBoInfo->dataVolume;
-   }
+   /* Adding UE Id to list of pending UEs to be scheduled */
+   addUeToBeScheduled(cell, ueId);
    return ROK;
 }
 
@@ -1354,7 +1347,162 @@ uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
 
    return ROK;
 }
+
+/*******************************************************************
+ *
+ * @brief Add UE to ueToBeScheduled List
+ *
+ * @details
+ *
+ *    Function : addUeToBeScheduled
+ *
+ *    Functionality:
+ *      Search if UE entry present in the list
+ *      If yes, return.
+ *      If no, add UE to the list
+ *
+ * @params[in] Cell control block
+ *             Ue Idx to be added
+ *
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t addUeToBeScheduled(SchCellCb *cell, uint8_t ueIdToAdd)
+{
+   uint8_t *ueId;
+   CmLList *node;
+
+   /* Search if UE entry is already present in ueToBeScheduled list.
+    * If yes, another entry for same UE not needed. Hence, return */
+   node = cell->ueToBeScheduled.first;
+   while(node)
+   {
+      ueId = (uint8_t *)node->node;
+      if(*ueId == ueIdToAdd)
+         return ROK;
+      node = node->next;
+   }
+
+   /* If UE entry not present already, add UE to the end of ueToBeScheduled list */
+   SCH_ALLOC(ueId, sizeof(uint8_t));
+   if(!ueId)
+   {
+      DU_LOG("\nERROR  -->  SCH : Memory allocation failure in addUeToBeScheduled");
+      return RFAILED;
+   }
+   *ueId = ueIdToAdd;
+   if(addNodeToLList(&cell->ueToBeScheduled, ueId, NULLP) != ROK)
+   {
+      DU_LOG("\nERROR  --> SCH : Failed to add UeIdx to cell->ueToBeScheduled list");
+      return RFAILED;
+   }
+   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
  **********************************************************************/