+/*******************************************************************************
+################################################################################
+# 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
+ **********************************************************************/