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