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