1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
18 /* header include files (.h) */
19 #include "common_def.h"
20 #include "du_app_mac_inf.h"
21 #include "mac_sch_interface.h"
22 #include "lwr_mac_upr_inf.h"
24 #include "mac_utils.h"
25 #include "mac_harq_dl.h"
26 #include "mac_ue_mgr.h"
29 * @brief Add HARQ process to UE's DL HARQ Entity
33 * Function : addDlHqProcInUe
35 * This functions adds HARQ process to UE's DL HARQ entity
37 * @param[in] Time of transmission on this HARQ process
39 * @param[in] DL Scheduling Information
43 void addDlHqProcInUe(SlotTimingInfo dlMsgTime, MacUeCb *ueCb, DlMsgSchInfo *schedInfo)
45 uint8_t hqProcId = 0, tbIdx = 0, cwIdx = 0;
46 DlHarqEnt *dlHqEnt = NULLP;
47 DlHarqProcCb *hqProcCb = NULLP;
49 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
50 hqProcId = schedInfo->harqProcNum;
51 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
53 /* Check if harqProcId is already present in UE's DL HARQ Entity */
54 if(hqProcCb->procId == schedInfo->harqProcNum)
56 /* Expected Behaviour:
57 * If a HARQ proc is already present in DL HARQ entity, it means this HARQ proc
58 * is not free and SCH must not schedule on this process.
60 * Corner Case (occured if this line is hit):
61 * HARQ proc is present in DL HARQ entity but SCH has scheduled a new data transmission on it.
64 * Free the process and schedule new data on it
66 for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
68 MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
70 memset(hqProcCb, 0, sizeof(DlHarqProcCb));
73 /* Fill HARQ Proc Cb */
74 hqProcCb->procId = hqProcId;
75 for(cwIdx = 0; cwIdx < schedInfo->dlMsgPdschCfg->numCodewords; cwIdx++)
77 memcpy(&hqProcCb->tbInfo[hqProcCb->numTb].txTime, &dlMsgTime, sizeof(SlotTimingInfo));
78 hqProcCb->tbInfo[hqProcCb->numTb].tbSize = schedInfo->dlMsgPdschCfg->codeword[cwIdx].tbSize;
85 * @brief Adds multiplexes TB to DL HARQ Process Info
89 * Function : updateNewTbInDlHqProcCb
91 * This function adds multiplxed TB to DL HARQ process.
92 * It will be used in case retransmission is required.
94 * @param[in] Time on which TB will be transmitted
96 * @param[in] Transport Block
101 uint8_t updateNewTbInDlHqProcCb(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint32_t tbSize, uint8_t *txPdu)
103 uint8_t hqProcIdx = 0, tbIdx = 0;
104 DlHarqEnt *dlHqEnt = NULLP;
105 DlTbInfo *tbInfo = NULLP;
107 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
109 /* Search HARQ Proc Cb in DL HARQ Ent */
110 for(hqProcIdx = 0; hqProcIdx < MAX_NUM_HARQ_PROC; hqProcIdx++)
112 /* Search TB Info in a HARQ Proc Cb */
113 for(tbIdx =0; tbIdx < dlHqEnt->harqProcCb[hqProcIdx].numTb; tbIdx++)
115 /* Store MAC PDU if a harqProcCb->tbInfo is found with
116 * a. same SFN/Slot on which incoming RLC DL Data is to be scheduled
117 * b. same TB size as MAC PDU size
119 if((dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.sfn == slotInfo.sfn) &&
120 (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.slot == slotInfo.slot) &&
121 (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].tbSize == tbSize))
123 tbInfo = &dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx];
124 MAC_ALLOC(tbInfo->tb, tbSize);
127 DU_LOG("\nERROR --> MAC : Failed to allocate memory for TB in updateTbInDlHqProcCb");
130 memcpy(tbInfo->tb, txPdu, tbSize);
140 * @brief Returns a transmission block from HARQ process Cb
144 * Function : fetchTbfromDlHarqProc
146 * Returns a transmission block from HARQ process Cb
148 * @param[in] Time of retransmission
150 * @param[in] HARQ process Id
156 uint8_t* fetchTbfromDlHarqProc(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint8_t hqProcId, uint32_t tbSize)
159 DlHarqEnt *dlHqEnt = NULLP;
160 DlHarqProcCb *hqProcCb = NULLP;
162 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
163 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
165 /* Search HARQ Proc Cb in DL HARQ Ent */
166 if(hqProcCb->procId == hqProcId)
168 /* Search TB Info in a HARQ Proc Cb */
169 for(tbIdx =0; tbIdx < hqProcCb->numTb; tbIdx++)
171 if(hqProcCb->tbInfo[tbIdx].tbSize == tbSize)
173 /* Update transmission time in TB Info */
174 memset(&hqProcCb->tbInfo[tbIdx].txTime, 0, sizeof(SlotTimingInfo));
175 memcpy(&hqProcCb->tbInfo[tbIdx].txTime, &slotInfo, sizeof(SlotTimingInfo));
177 return hqProcCb->tbInfo[tbIdx].tb;
184 * @brief Release Dl Harq process
188 * Function : fetchTbfromDlHarqProc
190 * Release Dl Harq process
192 * @param[in] Pst *pst, the post structure
193 * @param[in] SchRlsHqInfo *hqIndo, release hq info structure
198 uint8_t MacSchReleaseDlHarqProc(Pst *pst, SchRlsHqInfo *hqInfo)
200 uint8_t hqProcId, tbIdx = 0;
201 uint16_t cellIdx = 0, hqInfoIdx = 0, ueId = 0;
202 MacCellCb *cellCb = NULLP;
203 MacUeCb *ueCb = NULLP;
204 DlHarqEnt *dlHqEnt = NULLP;
205 DlHarqProcCb *hqProcCb = NULLP;
207 GET_CELL_IDX(hqInfo->cellId, cellIdx);
208 cellCb = macCb.macCell[cellIdx];
210 for(hqInfoIdx = 0; hqInfoIdx < hqInfo->numUes; hqInfoIdx++)
212 GET_UE_ID(hqInfo->ueHqInfo[hqInfoIdx].crnti, ueId)
213 ueCb = &cellCb->ueCb[ueId -1];
214 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
215 hqProcId = hqInfo->ueHqInfo[hqInfoIdx].hqProcId;
217 /* First check if the HARQ process to be released belong to msg 4 */
218 if ((ueCb->raCb) && (ueCb->raCb->msg4HqInfo.procId == hqProcId))
220 deleteMacRaCb(cellIdx, ueCb);
224 /* Search harqProcId in UE's DL HARQ Entity */
225 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
226 if(hqProcCb->procId == hqProcId)
228 /* Free HARQ process */
229 for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
231 MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
233 memset(hqProcCb, 0, sizeof(DlHarqProcCb));
234 hqProcCb->procId = MAX_NUM_HARQ_PROC;
239 MAC_FREE(hqInfo->ueHqInfo, (sizeof(SchUeHqInfo) * hqInfo->numUes));
240 MAC_FREE(hqInfo, sizeof(SchRlsHqInfo));
244 /**********************************************************************
246 **********************************************************************/