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