[Epic-ID: ODUHIGH-402][Task-ID: ODUHIGH-418] Harq feature changes
[o-du/l2.git] / src / 5gnrsch / sch_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 #include "common_def.h"
19 #include "tfu.h"
20 #include "lrg.h"
21 #include "tfu.x"
22 #include "lrg.x"
23 #include "du_log.h"
24 #include "du_app_mac_inf.h"
25 #include "mac_sch_interface.h"
26 #include "sch.h"
27 #include "sch_utils.h"
28 #include "cm_llist.h"
29
30 SchMacDlReleaseHarqFunc schMacDlReleaseHarqOpts[] =
31 {
32    packSchMacDlReleaseHarq,
33    MacSchReleaseDlHarqProc,
34    packSchMacDlReleaseHarq
35 };
36
37 typedef struct schCellCb SchCellCb;
38 typedef struct schUeCb SchUeCb;
39 void schDlHqEntReset(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqEnt *hqE);
40 void schDlHqAddToFreeList(SchDlHqProcCb *hqP);
41
42 /**
43  * @brief DL Harq entity intialization
44  *
45  * @details
46  *
47  *     Function : schDlHqEntInit
48  *      
49  *      This function intialize DL Harq entity
50  *           
51  *  @param[in]  SchCellCb *cellCb, cell cb pointer
52  *  @param[in]  SchUeCb *ueCb, ue cb pointer
53  *  @return  
54  *      -# void
55  **/
56 void schDlHqEntInit(SchCellCb *cellCb, SchUeCb *ueCb)
57 {
58    ueCb->dlHqEnt.numHqPrcs = SCH_MAX_NUM_DL_HQ_PROC;
59    ueCb->dlHqEnt.maxHqTx  = cellCb->cellCfg.schHqCfg.maxDlDataHqTx;
60    ueCb->dlHqEnt.cell = cellCb;
61    ueCb->dlHqEnt.ue =ueCb;
62    schDlHqEntReset(cellCb, ueCb, &ueCb->dlHqEnt);
63 }
64 /**
65  * @brief DL Harq entity Reset
66  *
67  * @details
68  *
69  *     Function : schDlHqEntReset
70  *      
71  *      This function Reset DL Harq entity
72  *           
73  *  @param[in]  SchCellCb *cellCb, cell cb pointer
74  *  @param[in]  SchUeCb *ueCb, ue cb pointer
75  *  @param[in]  SchDlHqEnt *hqE, Dl Harq entity pointer
76  *  @return  
77  *      -# void
78  **/
79 void schDlHqEntReset(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqEnt *hqE)
80 {
81    uint8_t count = 0;
82    SchDlHqProcCb *hqP = NULL;
83    cmLListInit(&hqE->free);
84    cmLListInit(&hqE->inUse);
85
86    for(count=0; count < hqE->numHqPrcs; count++)
87    {
88       hqP = &(hqE->procs[count]);
89       hqP->procId = count;
90       hqP->hqEnt = hqE;
91       hqP->maxHqTxPerHqP = hqE->maxHqTx;
92       hqP->dlHqEntLnk.node = (PTR)hqP;
93       hqP->dlHqProcLink.node = (PTR)hqP;
94       hqP->ulSlotLnk.node = (PTR)hqP;
95       schDlHqAddToFreeList(hqP);
96    }
97 }
98 /**
99  * @brief Add hq process to free list of DL Harq entity
100  *
101  * @details
102  *
103  *     Function : schDlHqAddToFreeList
104  *      
105  *      This function adds hq process to free list of DL Harq entity
106  *           
107  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
108  *  @return  
109  *      -# void
110  **/
111 void schDlHqAddToFreeList(SchDlHqProcCb *hqP)
112 {   
113    cmLListAdd2Tail(&(hqP->hqEnt->free), &hqP->dlHqEntLnk);
114 }
115 /**
116  * @brief Delete hq process from free list of DL Harq entity
117  *
118  * @details
119  *
120  *     Function : schDlHqDeleteFromFreeList
121  *      
122  *      This function deletes hq process to free list of DL Harq entity
123  *           
124  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
125  *  @return  
126  *      -# void
127  **/
128 void schDlHqDeleteFromFreeList(SchDlHqProcCb *hqP)
129 {
130    cmLListDelFrm(&(hqP->hqEnt->free), &hqP->dlHqEntLnk);
131 }
132 /**
133  * @brief Add hq process to in use list of DL Harq entity
134  *
135  * @details
136  *
137  *     Function : schDlHqAddToInUseList
138  *      
139  *      This function adds hq process to in use list of DL Harq entity
140  *           
141  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
142  *  @return  
143  *      -# void
144  **/
145 void schDlHqAddToInUseList(SchDlHqProcCb *hqP)
146 {
147    cmLListAdd2Tail(&(hqP->hqEnt->inUse), &hqP->dlHqEntLnk);
148 }
149 /**
150  * @brief Delete hq process from in use list of DL Harq entity
151  *
152  * @details
153  *
154  *     Function : schDlHqDeleteFromInUseList
155  *      
156  *      This function deletes hq process to in use list of DL Harq entity
157  *           
158  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
159  *  @return  
160  *      -# void
161  **/
162 void schDlHqDeleteFromInUseList(SchDlHqProcCb *hqP)
163 {   
164    cmLListDelFrm(&(hqP->hqEnt->inUse), &hqP->dlHqEntLnk);
165 }
166 /**
167  * @brief Get available Harq process from Harq entity
168  *
169  * @details
170  *
171  *     Function : schDlGetAvlHqProcess
172  *      
173  *      This function fetches hq process from free list and puts in in use list
174  *           
175  *  @param[in]  SchCellCb *cellCb, cell cb pointer
176  *  @param[in]  SchUeCb *ueCb, ue cb pointer
177  *  @param[in]  SchDlHqProcCb **hqP, Address of DL harq process pointer
178  *  @return  
179  *      -# ROK
180  *      -# RFAILED
181  **/
182 uint8_t schDlGetAvlHqProcess(SchCellCb *cellCb, SchUeCb *ueCb, SchDlHqProcCb **hqP)
183 {
184    SchDlHqProcCb *tmp;
185    if (ueCb->dlHqEnt.free.count == 0)
186    {
187       return RFAILED;
188    }
189    tmp = (SchDlHqProcCb*)(cmLListFirst(&(ueCb->dlHqEnt.free))->node);
190    if (NULLP == tmp)
191    {
192       return RFAILED;
193    }
194    schDlHqDeleteFromFreeList(tmp);
195    schDlHqAddToInUseList(tmp);
196    *hqP = tmp;
197    (*hqP)->maxHqTxPerHqP = ueCb->dlHqEnt.maxHqTx;
198    return ROK;
199 }
200 /**
201  * @brief Release Harq process from the DL Harq entity
202  *
203  * @details
204  *
205  *     Function : schDlReleaseHqProcess
206  *      
207  *      This function releases Harq process from DL Harq entity
208  *           
209  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
210  *  @return  
211  *      -# void
212  **/
213 void schDlReleaseHqProcess(SchDlHqProcCb *hqP)
214 {
215    cmLListDeleteLList(&hqP->dlLcPrbEst.dedLcList);
216    cmLListDeleteLList(&hqP->dlLcPrbEst.defLcList);
217    schDlHqDeleteFromInUseList(hqP);
218    schDlHqAddToFreeList(hqP);
219 }
220
221 /*******************************************************************
222  *
223  * @brief Handles sending DL HARQ process release to MAC 
224  *
225  * @details
226  *
227  *    Function : sendDlHarqProcReleaseToMac
228  *
229  *    Functionality:
230  *     Sends DL DL HARQ process release to MAC from SCH
231  *
232  * @params[in] 
233  * @return ROK     - success
234  *         RFAILED - failure
235  *
236  * ****************************************************************/
237 uint8_t sendDlHarqProcReleaseToMac(SchDlHqProcCb *hqP, Inst inst)
238 {
239    Pst pst;
240    SchRlsHqInfo *rlsHqInfo;
241    memset(&pst, 0, sizeof(Pst));
242    FILL_PST_SCH_TO_MAC(pst, inst);
243    pst.event = EVENT_DL_REL_HQ_PROC;
244
245    SCH_ALLOC(rlsHqInfo, sizeof(SchRlsHqInfo));
246    rlsHqInfo->cellId = hqP->hqEnt->cell->cellId;
247    rlsHqInfo->numUes = 1;
248
249    SCH_ALLOC(rlsHqInfo->ueHqInfo, sizeof(SchUeHqInfo)*rlsHqInfo->numUes);
250    rlsHqInfo->ueHqInfo[0].crnti = hqP->hqEnt->ue->crnti;
251    rlsHqInfo->ueHqInfo[0].hqProcId = hqP->procId;   
252
253    return(*schMacDlReleaseHarqOpts[pst.selector])(&pst, rlsHqInfo);
254 }
255 /**
256  * @brief Release Harq process TB from the DL Harq process
257  *
258  * @details
259  *
260  *     Function : schDlReleaseHqPTb
261  *      
262  *      This function releases Harq process TB from DL Harq proces
263  *           
264  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
265  *  @param[in]  uint8_t tbIdx, TB index
266  *  @param[in]  bool togNdi, indication to toggle NDI bit
267  *  @return  
268  *      -# void
269  **/
270 void schDlReleaseHqPTb(SchDlHqProcCb *hqP, uint8_t tbIdx, bool togNdi)
271 {
272    if (TRUE == togNdi)
273    {
274       hqP->tbInfo[tbIdx].ndi ^= 1;
275    }
276
277    {
278       hqP->tbInfo[tbIdx].isAckNackDtx = HQ_ACK;
279       hqP->tbInfo[tbIdx].isEnabled = FALSE;
280       hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
281       hqP->tbInfo[tbIdx].txCntr = 0;
282       if (HQ_TB_ACKED == hqP->tbInfo[tbIdx^1].state)
283       {
284          schDlReleaseHqProcess(hqP);
285          sendDlHarqProcReleaseToMac(hqP, hqP->hqEnt->cell->instIdx);
286       }
287    }
288 }
289 /**
290  * @brief Handles failure of HARQ process TB
291  *
292  * @details
293  *
294  *     Function : schDlHqTbFail
295  *      
296  *      This function handles failure of HARQ process TB
297  *           
298  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
299  *  @param[in]  uint8_t tbIdx, TB index
300  *  @param[in]  bool isMaxRetx, indicates max retransmission
301  *  @return  
302  *      -# void
303  **/
304 void schDlHqTbFail(SchDlHqProcCb *hqP, uint8_t tbIdx, bool isMaxRetx)
305 {
306    if (isMaxRetx)
307    {
308       schDlReleaseHqPTb(hqP, tbIdx, TRUE);
309    }
310    else
311    {
312       hqP->tbInfo[tbIdx].state = HQ_TB_NACKED;
313       if (HQ_TB_WAITING == hqP->tbInfo[tbIdx^1].state)
314       {
315          cmLListAdd2Tail( &(hqP->hqEnt->ue->dlRetxHqList), &hqP->dlHqProcLink);
316       }
317    }
318 }
319 /**
320  * @brief Handles Harq feedback for MSG4
321  *
322  * @details
323  *
324  *     Function : schMsg4FeedbackUpdate
325  *      
326  *      This function handles Harq feedback for MSG4
327  *           
328  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
329  *  @param[in]  uint8_t fdbk, Received feedback
330  *  @return  
331  *      -# void
332  **/
333 void schMsg4FeedbackUpdate(SchDlHqProcCb *hqP, uint8_t fdbk)
334 {
335    hqP->tbInfo[0].isAckNackDtx = fdbk;
336    hqP->tbInfo[1].isAckNackDtx = HQ_TB_ACKED;
337    if (HQ_TB_ACKED == hqP->tbInfo[0].isAckNackDtx)
338    {
339       schDlReleaseHqPTb(hqP, 0, TRUE);
340       schDlReleaseHqPTb(hqP, 1, TRUE);
341       schMsg4Complete(hqP->hqEnt->ue);
342    }
343    else
344    {
345       if( hqP->tbInfo[0].txCntr >= hqP->hqEnt->cell->cellCfg.schHqCfg.maxMsg4HqTx)
346       {
347          schDlReleaseHqProcess(hqP);
348          hqP->hqEnt->ue->msg4Proc = NULLP;
349          hqP->hqEnt->ue->retxMsg4HqProc = NULLP;
350          /* Delete UE and RA context */
351       }
352       addUeToBeScheduled(hqP->hqEnt->cell,hqP->hqEnt->ue->ueId);
353       hqP->hqEnt->ue->retxMsg4HqProc = hqP;
354    }
355 }
356 /**
357  * @brief Handles Harq feedback for DL Data
358  *
359  * @details
360  *
361  *     Function : schDlHqFeedbackUpdate
362  *      
363  *      This function handles Harq feedback for DL data
364  *           
365  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
366  *  @param[in]  uint8_t fdbk1, Received feedback for TB -0
367  *  @param[in]  uint8_t fdbk2, Received feedback for TB -1
368  *  @return  
369  *      -# void
370  **/
371 void schDlHqFeedbackUpdate(SchDlHqProcCb *hqP, uint8_t fdbk1, uint8_t fdbk2)
372 {
373    uint8_t tbIdx;
374    for (tbIdx = 0; tbIdx <2; tbIdx++)
375    {
376       if (HQ_TB_WAITING == hqP->tbInfo[tbIdx].state)
377       {
378          hqP->tbInfo[tbIdx].isAckNackDtx = (0 == tbIdx)?fdbk1:fdbk2;
379       }
380       if (TRUE == hqP->tbInfo[tbIdx].isEnabled)
381       {
382          if (HQ_TB_ACKED == hqP->tbInfo[tbIdx].isAckNackDtx)
383          {
384             schDlReleaseHqPTb(hqP, tbIdx, TRUE);
385          }
386          else
387          {
388             if(hqP->tbInfo[tbIdx].txCntr >= hqP->maxHqTxPerHqP)
389             {
390                schDlHqTbFail(hqP, tbIdx, TRUE);
391             }
392             else
393             {
394                schDlHqTbFail(hqP, tbIdx, FALSE);
395                addUeToBeScheduled(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
396             }
397          }
398       }
399    }
400 }
401 /**********************************************************************
402   End of file
403  **********************************************************************/