Merge "[Epic-ID: ODUHIGH-402][Task-ID: ODUHIGH-418] Harq feature changes"
[o-du/l2.git] / src / 5gnrmac / mac_harq_dl.c
diff --git a/src/5gnrmac/mac_harq_dl.c b/src/5gnrmac/mac_harq_dl.c
new file mode 100644 (file)
index 0000000..8b3499f
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************
+################################################################################
+#   Copyright (c) [2017-2019] [Radisys]                                        #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+ *******************************************************************************/
+/* header include files (.h) */
+#include "common_def.h"
+#include "du_app_mac_inf.h"
+#include "mac_sch_interface.h"
+#include "lwr_mac_upr_inf.h"
+#include "mac.h"
+#include "mac_utils.h"
+#include "mac_harq_dl.h"
+
+/**
+ * @brief Add HARQ process to UE's DL HARQ Entity
+ *
+ * @details
+ *
+ *     Function : addDlHqProcInUe
+ *
+ *      This functions adds HARQ process to UE's DL HARQ entity
+ *
+ *  @param[in]  Time of transmission on this HARQ process
+ *  @param[in]  UE Cb
+ *  @param[in]  DL Scheduling Information
+ *  @return
+ *      -# Void
+ **/
+void addDlHqProcInUe(SlotTimingInfo dlMsgTime, MacUeCb *ueCb, DlMsgSchInfo schedInfo)
+{
+   uint8_t       hqProcId = 0, tbIdx = 0, cwIdx = 0;
+   DlHarqEnt     *dlHqEnt = NULLP;
+   DlHarqProcCb  *hqProcCb = NULLP;
+
+   dlHqEnt = &ueCb->dlInfo.dlHarqEnt;  
+   hqProcId = schedInfo.dlMsgInfo.harqProcNum;
+   hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
+
+   /* Check if harqProcId is already present in UE's DL HARQ Entity */
+   if(hqProcCb->procId == schedInfo.dlMsgInfo.harqProcNum)
+   {
+      /* Expected Behaviour:
+       * If a HARQ proc is already present in DL HARQ entity, it means this HARQ proc 
+       * is not free and SCH must not schedule on this process.
+       *
+       * Corner Case (occured if this line is hit):
+       * HARQ proc is present in DL HARQ entity but SCH has scheduled a new data transmission on it.
+       *
+       * Action:
+       * Free the process and schedule new data on it
+       */
+      for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
+      {
+         MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
+      }
+      memset(hqProcCb, 0, sizeof(DlHarqProcCb));
+   }
+
+   /* Fill HARQ Proc Cb */
+   hqProcCb->procId = hqProcId;
+   for(cwIdx = 0; cwIdx < schedInfo.dlMsgPdschCfg.numCodewords; cwIdx++)
+   {
+      memcpy(&hqProcCb->tbInfo[hqProcCb->numTb].txTime, &dlMsgTime, sizeof(SlotTimingInfo));
+      hqProcCb->tbInfo[hqProcCb->numTb].tbSize = schedInfo.dlMsgPdschCfg.codeword[cwIdx].tbSize;
+      hqProcCb->numTb++;
+   }
+   return;
+}
+
+/**
+ * @brief Adds multiplexes TB to DL HARQ Process Info
+ *
+ * @details
+ *
+ *     Function : updateNewTbInDlHqProcCb
+ *     
+ *      This function adds multiplxed TB to DL HARQ process.
+ *      It will be used in case retransmission is required.
+ *           
+ *  @param[in]  Time on which TB will be transmitted
+ *  @param[in]  UE CB
+ *  @param[in]  Transport Block
+ *  @return  
+ *      -# ROK 
+ *      -# RFAILED 
+ **/
+uint8_t updateNewTbInDlHqProcCb(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint32_t tbSize, uint8_t *txPdu)
+{
+   uint8_t hqProcIdx = 0, tbIdx = 0;
+   DlHarqEnt  *dlHqEnt = NULLP;
+   DlTbInfo   *tbInfo = NULLP;
+
+   dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
+
+   /* Search HARQ Proc Cb in DL HARQ Ent */
+   for(hqProcIdx = 0; hqProcIdx < MAX_NUM_HARQ_PROC; hqProcIdx++)
+   {
+      /* Search TB Info in a HARQ Proc Cb */
+      for(tbIdx =0; tbIdx < dlHqEnt->harqProcCb[hqProcIdx].numTb; tbIdx++)
+      {
+         /* Store MAC PDU if a harqProcCb->tbInfo is found with 
+          * a. same SFN/Slot on which incoming RLC DL Data is to be scheduled
+          * b. same TB size as MAC PDU size
+          */
+         if((dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.sfn == slotInfo.sfn) &&
+               (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.slot == slotInfo.slot) &&
+               (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].tbSize == tbSize))
+         {
+            tbInfo = &dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx];
+            MAC_ALLOC(tbInfo->tb, tbSize);
+            if(!tbInfo->tb)
+            {
+               DU_LOG("\nERROR  -->  MAC : Failed to allocate memory for TB in updateTbInDlHqProcCb");
+               return RFAILED;
+            }
+            memcpy(tbInfo->tb, txPdu, tbSize);
+
+            return ROK;
+         }
+      }
+   }
+   return RFAILED;
+}
+
+/**
+ * @brief Returns a transmission block from HARQ process Cb
+ *
+ * @details
+ *
+ *     Function : fetchTbfromDlHarqProc
+ *      
+ *      Returns a transmission block from HARQ process Cb
+ *           
+ *  @param[in]  Time of retransmission
+ *  @param[in]  UE CB
+ *  @param[in]  HARQ process Id
+ *  @param[in]  TB size
+ *  @return  
+ *      -# Pointer to TB
+ *      -# NULL
+ **/
+uint8_t* fetchTbfromDlHarqProc(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint8_t hqProcId, uint32_t tbSize)
+{
+   uint8_t    tbIdx = 0;
+   DlHarqEnt  *dlHqEnt = NULLP;
+   DlHarqProcCb  *hqProcCb = NULLP;
+
+   dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
+   hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
+
+   /* Search HARQ Proc Cb in DL HARQ Ent */
+   if(hqProcCb->procId == hqProcId)
+   {
+      /* Search TB Info in a HARQ Proc Cb */
+      for(tbIdx =0; tbIdx < hqProcCb->numTb; tbIdx++)
+      {
+         if(hqProcCb->tbInfo[tbIdx].tbSize == tbSize)
+         {
+            /* Update transmission time in TB Info */
+            memset(&hqProcCb->tbInfo[tbIdx].txTime, 0, sizeof(SlotTimingInfo));
+            memcpy(&hqProcCb->tbInfo[tbIdx].txTime, &slotInfo, sizeof(SlotTimingInfo));
+
+            return hqProcCb->tbInfo[tbIdx].tb;
+         }
+      }
+   }
+   return NULLP;
+}
+/**
+ * @brief Release Dl Harq process
+ *
+ * @details
+ *
+ *     Function : fetchTbfromDlHarqProc
+ *      
+ *      Release Dl Harq process
+ *           
+ *  @param[in]  Pst *pst, the post structure
+ *  @param[in]  SchRlsHqInfo *hqIndo, release hq info structure
+  *  @return  
+ *      -# ROK
+ *      -# RFAILED
+ **/
+uint8_t MacSchReleaseDlHarqProc(Pst *pst, SchRlsHqInfo *hqInfo)
+{
+   uint8_t   hqProcId, tbIdx = 0;
+   uint16_t  cellIdx = 0, hqInfoIdx = 0, ueId = 0;
+   MacCellCb *cellCb = NULLP;
+   MacUeCb   *ueCb = NULLP;
+   DlHarqEnt     *dlHqEnt = NULLP;
+   DlHarqProcCb  *hqProcCb = NULLP;
+
+   GET_CELL_IDX(hqInfo->cellId, cellIdx);
+   cellCb = macCb.macCell[cellIdx];
+
+   for(hqInfoIdx = 0; hqInfoIdx < hqInfo->numUes; hqInfoIdx++)
+   {
+      GET_UE_ID(hqInfo->ueHqInfo[hqInfoIdx].crnti, ueId)
+      ueCb = &cellCb->ueCb[ueId -1];
+      dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
+      hqProcId = hqInfo->ueHqInfo[hqInfoIdx].hqProcId;
+
+      /* First check if the HARQ process to be released belong to msg 4 */
+      if ((ueCb->raCb) && (ueCb->raCb->msg4HqInfo.procId == hqProcId))
+      {
+            deleteMacRaCb(cellIdx, ueCb);
+      }
+      else
+      {
+         /* Search harqProcId in UE's DL HARQ Entity */
+         hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
+         if(hqProcCb->procId == hqProcId)
+         {
+            /* Free HARQ process */
+            for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
+            {
+               MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
+            }
+            memset(hqProcCb, 0, sizeof(DlHarqProcCb));
+            hqProcCb->procId =  MAX_NUM_HARQ_PROC;
+         }
+      }
+   }
+   
+   MAC_FREE(hqInfo->ueHqInfo, (sizeof(SchUeHqInfo) * hqInfo->numUes)); 
+   MAC_FREE(hqInfo, sizeof(SchRlsHqInfo));
+   return ROK;
+}
+
+/**********************************************************************
+  End of file
+ **********************************************************************/