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