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"
28 * @brief Add HARQ process to UE's DL HARQ Entity
32 * Function : addDlHqProcInUe
34 * This functions adds HARQ process to UE's DL HARQ entity
36 * @param[in] Time of transmission on this HARQ process
38 * @param[in] DL Scheduling Information
42 void addDlHqProcInUe(SlotTimingInfo dlMsgTime, MacUeCb *ueCb, DlMsgSchInfo schedInfo)
44 uint8_t hqProcId = 0, tbIdx = 0, cwIdx = 0;
45 DlHarqEnt *dlHqEnt = NULLP;
46 DlHarqProcCb *hqProcCb = NULLP;
48 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
49 hqProcId = schedInfo.dlMsgInfo.harqProcNum;
50 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
52 /* Check if harqProcId is already present in UE's DL HARQ Entity */
53 if(hqProcCb->procId == schedInfo.dlMsgInfo.harqProcNum)
55 /* Expected Behaviour:
56 * If a HARQ proc is already present in DL HARQ entity, it means this HARQ proc
57 * is not free and SCH must not schedule on this process.
59 * Corner Case (occured if this line is hit):
60 * HARQ proc is present in DL HARQ entity but SCH has scheduled a new data transmission on it.
63 * Free the process and schedule new data on it
65 for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
67 MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
69 memset(hqProcCb, 0, sizeof(DlHarqProcCb));
72 /* Fill HARQ Proc Cb */
73 hqProcCb->procId = hqProcId;
74 for(cwIdx = 0; cwIdx < schedInfo.dlMsgPdschCfg.numCodewords; cwIdx++)
76 memcpy(&hqProcCb->tbInfo[hqProcCb->numTb].txTime, &dlMsgTime, sizeof(SlotTimingInfo));
77 hqProcCb->tbInfo[hqProcCb->numTb].tbSize = schedInfo.dlMsgPdschCfg.codeword[cwIdx].tbSize;
84 * @brief Adds multiplexes TB to DL HARQ Process Info
88 * Function : updateNewTbInDlHqProcCb
90 * This function adds multiplxed TB to DL HARQ process.
91 * It will be used in case retransmission is required.
93 * @param[in] Time on which TB will be transmitted
95 * @param[in] Transport Block
100 uint8_t updateNewTbInDlHqProcCb(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint32_t tbSize, uint8_t *txPdu)
102 uint8_t hqProcIdx = 0, tbIdx = 0;
103 DlHarqEnt *dlHqEnt = NULLP;
104 DlTbInfo *tbInfo = NULLP;
106 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
108 /* Search HARQ Proc Cb in DL HARQ Ent */
109 for(hqProcIdx = 0; hqProcIdx < MAX_NUM_HARQ_PROC; hqProcIdx++)
111 /* Search TB Info in a HARQ Proc Cb */
112 for(tbIdx =0; tbIdx < dlHqEnt->harqProcCb[hqProcIdx].numTb; tbIdx++)
114 /* Store MAC PDU if a harqProcCb->tbInfo is found with
115 * a. same SFN/Slot on which incoming RLC DL Data is to be scheduled
116 * b. same TB size as MAC PDU size
118 if((dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.sfn == slotInfo.sfn) &&
119 (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].txTime.slot == slotInfo.slot) &&
120 (dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx].tbSize == tbSize))
122 tbInfo = &dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx];
123 MAC_ALLOC(tbInfo->tb, tbSize);
126 DU_LOG("\nERROR --> MAC : Failed to allocate memory for TB in updateTbInDlHqProcCb");
129 memcpy(tbInfo->tb, txPdu, tbSize);
139 * @brief Returns a transmission block from HARQ process Cb
143 * Function : fetchTbfromDlHarqProc
145 * Returns a transmission block from HARQ process Cb
147 * @param[in] Time of retransmission
149 * @param[in] HARQ process Id
155 uint8_t* fetchTbfromDlHarqProc(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint8_t hqProcId, uint32_t tbSize)
158 DlHarqEnt *dlHqEnt = NULLP;
159 DlHarqProcCb *hqProcCb = NULLP;
161 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
162 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
164 /* Search HARQ Proc Cb in DL HARQ Ent */
165 if(hqProcCb->procId == hqProcId)
167 /* Search TB Info in a HARQ Proc Cb */
168 for(tbIdx =0; tbIdx < hqProcCb->numTb; tbIdx++)
170 if(hqProcCb->tbInfo[tbIdx].tbSize == tbSize)
172 /* Update transmission time in TB Info */
173 memset(&hqProcCb->tbInfo[tbIdx].txTime, 0, sizeof(SlotTimingInfo));
174 memcpy(&hqProcCb->tbInfo[tbIdx].txTime, &slotInfo, sizeof(SlotTimingInfo));
176 return hqProcCb->tbInfo[tbIdx].tb;
183 * @brief Release Dl Harq process
187 * Function : fetchTbfromDlHarqProc
189 * Release Dl Harq process
191 * @param[in] Pst *pst, the post structure
192 * @param[in] SchRlsHqInfo *hqIndo, release hq info structure
197 uint8_t MacSchReleaseDlHarqProc(Pst *pst, SchRlsHqInfo *hqInfo)
199 uint8_t hqProcId, tbIdx = 0;
200 uint16_t cellIdx = 0, hqInfoIdx = 0, ueId = 0;
201 MacCellCb *cellCb = NULLP;
202 MacUeCb *ueCb = NULLP;
203 DlHarqEnt *dlHqEnt = NULLP;
204 DlHarqProcCb *hqProcCb = NULLP;
206 GET_CELL_IDX(hqInfo->cellId, cellIdx);
207 cellCb = macCb.macCell[cellIdx];
209 for(hqInfoIdx = 0; hqInfoIdx < hqInfo->numUes; hqInfoIdx++)
211 GET_UE_ID(hqInfo->ueHqInfo[hqInfoIdx].crnti, ueId)
212 ueCb = &cellCb->ueCb[ueId -1];
213 dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
214 hqProcId = hqInfo->ueHqInfo[hqInfoIdx].hqProcId;
216 /* First check if the HARQ process to be released belong to msg 4 */
217 if ((ueCb->raCb) && (ueCb->raCb->msg4HqInfo.procId == hqProcId))
219 deleteMacRaCb(cellIdx, ueCb);
223 /* Search harqProcId in UE's DL HARQ Entity */
224 hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
225 if(hqProcCb->procId == hqProcId)
227 /* Free HARQ process */
228 for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
230 MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
232 memset(hqProcCb, 0, sizeof(DlHarqProcCb));
233 hqProcCb->procId = MAX_NUM_HARQ_PROC;
238 MAC_FREE(hqInfo->ueHqInfo, (sizeof(SchUeHqInfo) * hqInfo->numUes));
239 MAC_FREE(hqInfo, sizeof(SchRlsHqInfo));
243 /**********************************************************************
245 **********************************************************************/