[JIRA ID- ODUHIGH-462] [ISSUE ID ODUHIGH-477] Adding support for drx configuration...
[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    if(hqP)
216    {
217       cmLListDeleteLList(&hqP->dlLcPrbEst.dedLcList);
218       cmLListDeleteLList(&hqP->dlLcPrbEst.defLcList);
219       schDlHqDeleteFromInUseList(hqP);
220       schDlHqAddToFreeList(hqP);
221    }
222 }
223
224 /*******************************************************************
225  *
226  * @brief Handles sending DL HARQ process release to MAC 
227  *
228  * @details
229  *
230  *    Function : sendDlHarqProcReleaseToMac
231  *
232  *    Functionality:
233  *     Sends DL DL HARQ process release to MAC from SCH
234  *
235  * @params[in] 
236  * @return ROK     - success
237  *         RFAILED - failure
238  *
239  * ****************************************************************/
240 uint8_t sendDlHarqProcReleaseToMac(SchDlHqProcCb *hqP, Inst inst)
241 {
242    Pst pst;
243    SchRlsHqInfo *rlsHqInfo;
244    memset(&pst, 0, sizeof(Pst));
245    FILL_PST_SCH_TO_MAC(pst, inst);
246    pst.event = EVENT_DL_REL_HQ_PROC;
247
248    SCH_ALLOC(rlsHqInfo, sizeof(SchRlsHqInfo));
249    rlsHqInfo->cellId = hqP->hqEnt->cell->cellId;
250    rlsHqInfo->numUes = 1;
251
252    SCH_ALLOC(rlsHqInfo->ueHqInfo, sizeof(SchUeHqInfo)*rlsHqInfo->numUes);
253    rlsHqInfo->ueHqInfo[0].crnti = hqP->hqEnt->ue->crnti;
254    rlsHqInfo->ueHqInfo[0].hqProcId = hqP->procId;   
255
256    return(*schMacDlReleaseHarqOpts[pst.selector])(&pst, rlsHqInfo);
257 }
258 /**
259  * @brief Release Harq process TB from the DL Harq process
260  *
261  * @details
262  *
263  *     Function : schDlReleaseHqPTb
264  *      
265  *      This function releases Harq process TB from DL Harq proces
266  *           
267  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
268  *  @param[in]  uint8_t tbIdx, TB index
269  *  @param[in]  bool togNdi, indication to toggle NDI bit
270  *  @return  
271  *      -# void
272  **/
273 void schDlReleaseHqPTb(SchDlHqProcCb *hqP, uint8_t tbIdx, bool togNdi)
274 {
275    if (TRUE == togNdi)
276    {
277       hqP->tbInfo[tbIdx].ndi ^= 1;
278    }
279
280    {
281       hqP->tbInfo[tbIdx].isAckNackDtx = HQ_ACK;
282       hqP->tbInfo[tbIdx].isEnabled = FALSE;
283       hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
284       hqP->tbInfo[tbIdx].txCntr = 0;
285       if (HQ_TB_ACKED == hqP->tbInfo[tbIdx^1].state)
286       {
287          schDlReleaseHqProcess(hqP);
288          sendDlHarqProcReleaseToMac(hqP, hqP->hqEnt->cell->instIdx);
289       }
290    }
291 }
292 /**
293  * @brief Handles failure of HARQ process TB
294  *
295  * @details
296  *
297  *     Function : schDlHqTbFail
298  *      
299  *      This function handles failure of HARQ process TB
300  *           
301  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
302  *  @param[in]  uint8_t tbIdx, TB index
303  *  @param[in]  bool isMaxRetx, indicates max retransmission
304  *  @return  
305  *      -# void
306  **/
307 void schDlHqTbFail(SchDlHqProcCb *hqP, uint8_t tbIdx, bool isMaxRetx)
308 {
309    if (isMaxRetx)
310    {
311       schDlReleaseHqPTb(hqP, tbIdx, TRUE);
312    }
313    else
314    {
315       hqP->tbInfo[tbIdx].state = HQ_TB_NACKED;
316       if (HQ_TB_WAITING == hqP->tbInfo[tbIdx^1].state)
317       {
318          cmLListAdd2Tail( &(hqP->hqEnt->ue->dlRetxHqList), &hqP->dlHqProcLink);
319       }
320    }
321 }
322 /**
323  * @brief Handles Harq feedback for MSG4
324  *
325  * @details
326  *
327  *     Function : schMsg4FeedbackUpdate
328  *      
329  *      This function handles Harq feedback for MSG4
330  *           
331  *  @param[in]  SchDlHqProcCb *hqP, DL harq process pointer
332  *  @param[in]  uint8_t fdbk, Received feedback
333  *  @return  
334  *      -# void
335  **/
336 void schMsg4FeedbackUpdate(SchDlHqProcCb *hqP, uint8_t fdbk)
337 {
338    hqP->tbInfo[0].isAckNackDtx = fdbk;
339    hqP->tbInfo[1].isAckNackDtx = HQ_TB_ACKED;
340    if (HQ_TB_ACKED == hqP->tbInfo[0].isAckNackDtx)
341    {
342       schDlReleaseHqPTb(hqP, 0, TRUE);
343       schDlReleaseHqPTb(hqP, 1, TRUE);
344       schMsg4Complete(hqP->hqEnt->ue);
345    }
346    else
347    {
348       if( hqP->tbInfo[0].txCntr >= hqP->hqEnt->cell->cellCfg.schHqCfg.maxMsg4HqTx)
349       {
350          schDlReleaseHqProcess(hqP);
351          hqP->hqEnt->ue->msg4Proc = NULLP;
352          hqP->hqEnt->ue->retxMsg4HqProc = NULLP;
353          /* Delete UE and RA context */
354       }
355       addUeToBeScheduled(hqP->hqEnt->cell,hqP->hqEnt->ue->ueId);
356       hqP->hqEnt->ue->retxMsg4HqProc = hqP;
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                addUeToBeScheduled(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
399             }
400          }
401       }
402    }
403 }
404 /**********************************************************************
405   End of file
406  **********************************************************************/