[Epic-ID: ODUHIGH-402][Task-ID: ODUHIGH-418] Harq feature changes
[o-du/l2.git] / src / 5gnrmac / mac_harq_dl.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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"
23 #include "mac.h"
24 #include "mac_utils.h"
25 #include "mac_harq_dl.h"
26
27 /**
28  * @brief Add HARQ process to UE's DL HARQ Entity
29  *
30  * @details
31  *
32  *     Function : addDlHqProcInUe
33  *
34  *      This functions adds HARQ process to UE's DL HARQ entity
35  *
36  *  @param[in]  Time of transmission on this HARQ process
37  *  @param[in]  UE Cb
38  *  @param[in]  DL Scheduling Information
39  *  @return
40  *      -# Void
41  **/
42 void addDlHqProcInUe(SlotTimingInfo dlMsgTime, MacUeCb *ueCb, DlMsgSchInfo schedInfo)
43 {
44    uint8_t       hqProcId = 0, tbIdx = 0, cwIdx = 0;
45    DlHarqEnt     *dlHqEnt = NULLP;
46    DlHarqProcCb  *hqProcCb = NULLP;
47
48    dlHqEnt = &ueCb->dlInfo.dlHarqEnt;  
49    hqProcId = schedInfo.dlMsgInfo.harqProcNum;
50    hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
51
52    /* Check if harqProcId is already present in UE's DL HARQ Entity */
53    if(hqProcCb->procId == schedInfo.dlMsgInfo.harqProcNum)
54    {
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.
58        *
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.
61        *
62        * Action:
63        * Free the process and schedule new data on it
64        */
65       for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
66       {
67          MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
68       }
69       memset(hqProcCb, 0, sizeof(DlHarqProcCb));
70    }
71
72    /* Fill HARQ Proc Cb */
73    hqProcCb->procId = hqProcId;
74    for(cwIdx = 0; cwIdx < schedInfo.dlMsgPdschCfg.numCodewords; cwIdx++)
75    {
76       memcpy(&hqProcCb->tbInfo[hqProcCb->numTb].txTime, &dlMsgTime, sizeof(SlotTimingInfo));
77       hqProcCb->tbInfo[hqProcCb->numTb].tbSize = schedInfo.dlMsgPdschCfg.codeword[cwIdx].tbSize;
78       hqProcCb->numTb++;
79    }
80    return;
81 }
82
83 /**
84  * @brief Adds multiplexes TB to DL HARQ Process Info
85  *
86  * @details
87  *
88  *     Function : updateNewTbInDlHqProcCb
89  *     
90  *      This function adds multiplxed TB to DL HARQ process.
91  *      It will be used in case retransmission is required.
92  *           
93  *  @param[in]  Time on which TB will be transmitted
94  *  @param[in]  UE CB
95  *  @param[in]  Transport Block
96  *  @return  
97  *      -# ROK 
98  *      -# RFAILED 
99  **/
100 uint8_t updateNewTbInDlHqProcCb(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint32_t tbSize, uint8_t *txPdu)
101 {
102    uint8_t hqProcIdx = 0, tbIdx = 0;
103    DlHarqEnt  *dlHqEnt = NULLP;
104    DlTbInfo   *tbInfo = NULLP;
105
106    dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
107
108    /* Search HARQ Proc Cb in DL HARQ Ent */
109    for(hqProcIdx = 0; hqProcIdx < MAX_NUM_HARQ_PROC; hqProcIdx++)
110    {
111       /* Search TB Info in a HARQ Proc Cb */
112       for(tbIdx =0; tbIdx < dlHqEnt->harqProcCb[hqProcIdx].numTb; tbIdx++)
113       {
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
117           */
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))
121          {
122             tbInfo = &dlHqEnt->harqProcCb[hqProcIdx].tbInfo[tbIdx];
123             MAC_ALLOC(tbInfo->tb, tbSize);
124             if(!tbInfo->tb)
125             {
126                DU_LOG("\nERROR  -->  MAC : Failed to allocate memory for TB in updateTbInDlHqProcCb");
127                return RFAILED;
128             }
129             memcpy(tbInfo->tb, txPdu, tbSize);
130
131             return ROK;
132          }
133       }
134    }
135    return RFAILED;
136 }
137
138 /**
139  * @brief Returns a transmission block from HARQ process Cb
140  *
141  * @details
142  *
143  *     Function : fetchTbfromDlHarqProc
144  *      
145  *      Returns a transmission block from HARQ process Cb
146  *           
147  *  @param[in]  Time of retransmission
148  *  @param[in]  UE CB
149  *  @param[in]  HARQ process Id
150  *  @param[in]  TB size
151  *  @return  
152  *      -# Pointer to TB
153  *      -# NULL
154  **/
155 uint8_t* fetchTbfromDlHarqProc(SlotTimingInfo slotInfo, MacUeCb *ueCb, uint8_t hqProcId, uint32_t tbSize)
156 {
157    uint8_t    tbIdx = 0;
158    DlHarqEnt  *dlHqEnt = NULLP;
159    DlHarqProcCb  *hqProcCb = NULLP;
160
161    dlHqEnt = &ueCb->dlInfo.dlHarqEnt;
162    hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
163
164    /* Search HARQ Proc Cb in DL HARQ Ent */
165    if(hqProcCb->procId == hqProcId)
166    {
167       /* Search TB Info in a HARQ Proc Cb */
168       for(tbIdx =0; tbIdx < hqProcCb->numTb; tbIdx++)
169       {
170          if(hqProcCb->tbInfo[tbIdx].tbSize == tbSize)
171          {
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));
175
176             return hqProcCb->tbInfo[tbIdx].tb;
177          }
178       }
179    }
180    return NULLP;
181 }
182 /**
183  * @brief Release Dl Harq process
184  *
185  * @details
186  *
187  *     Function : fetchTbfromDlHarqProc
188  *      
189  *      Release Dl Harq process
190  *           
191  *  @param[in]  Pst *pst, the post structure
192  *  @param[in]  SchRlsHqInfo *hqIndo, release hq info structure
193   *  @return  
194  *      -# ROK
195  *      -# RFAILED
196  **/
197 uint8_t MacSchReleaseDlHarqProc(Pst *pst, SchRlsHqInfo *hqInfo)
198 {
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;
205
206    GET_CELL_IDX(hqInfo->cellId, cellIdx);
207    cellCb = macCb.macCell[cellIdx];
208
209    for(hqInfoIdx = 0; hqInfoIdx < hqInfo->numUes; hqInfoIdx++)
210    {
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;
215
216       /* First check if the HARQ process to be released belong to msg 4 */
217       if ((ueCb->raCb) && (ueCb->raCb->msg4HqInfo.procId == hqProcId))
218       {
219             deleteMacRaCb(cellIdx, ueCb);
220       }
221       else
222       {
223          /* Search harqProcId in UE's DL HARQ Entity */
224          hqProcCb = &dlHqEnt->harqProcCb[hqProcId];
225          if(hqProcCb->procId == hqProcId)
226          {
227             /* Free HARQ process */
228             for(tbIdx = 0; tbIdx < hqProcCb->numTb; tbIdx++)
229             {
230                MAC_FREE(hqProcCb->tbInfo[tbIdx].tb, hqProcCb->tbInfo[tbIdx].tbSize);
231             }
232             memset(hqProcCb, 0, sizeof(DlHarqProcCb));
233             hqProcCb->procId =  MAX_NUM_HARQ_PROC;
234          }
235       }
236    }
237    
238    MAC_FREE(hqInfo->ueHqInfo, (sizeof(SchUeHqInfo) * hqInfo->numUes)); 
239    MAC_FREE(hqInfo, sizeof(SchRlsHqInfo));
240    return ROK;
241 }
242
243 /**********************************************************************
244   End of file
245  **********************************************************************/