RLC BO, BO response and DL Data handling. [Issue-ID: ODUHIGH-181]
[o-du/l2.git] / src / 5gnrrlc / kw_lim.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
19 /********************************************************************20**
20   
21      Name:    LTE-RLC Layer - Lower Interface Functions
22     
23      Type:    C file
24   
25      Desc:     Source code for RLC Lower Interface Module.
26                This file contains following functions
27       
28         --RlcLiRguBndCfm
29         --rlcProcCommLcUlData
30         --rlcProcDedLcUlData
31         --rlcProcCommLcSchedRpt
32         --rlcProcDedLcSchedRpt
33         --RlcLiRguHqStaInd
34
35      File:     kw_lim.c
36
37 **********************************************************************/
38 static const char* RLOG_MODULE_NAME="LIM";
39 static int RLOG_MODULE_ID=2048;
40 static int RLOG_FILE_ID=196;
41
42 /** 
43  * @file kw_lim.c
44  * @brief RLC Lower Interface module
45 */
46
47 #define RLC_MODULE RLC_DBGMASK_INF
48
49 \f
50 /* header (.h) include files */
51 #include "common_def.h"
52 #include "lkw.h"           /* LKW defines */
53 #include "ckw.h"           /* CKW defines */
54 #include "kwu.h"           /* KWU defines */
55 #include "rgu.h"           /* RGU defines */
56 #include "kw_err.h"
57 #include "kw_env.h"        /* RLC environment options */
58
59 #include "kw.h"            /* RLC defines */
60 #include "kw_udx.h"
61 #include "kw_dl.h"
62 #include "kw_ul.h"
63
64 /* extern (.x) include files */
65 #include "lkw.x"           /* LKW */
66 #include "ckw.x"           /* CKW */
67 #include "kwu.x"           /* KWU */
68 #include "rgu.x"           /* RGU */
69
70 #include "kw.x"
71 #include "kw_udx.x"
72 #include "kw_dl.x"
73 #include "kw_ul.x"
74 #include "rlc_utils.h"
75 #include "rlc_mac_inf.h"
76
77 #ifdef __cplusplus
78 EXTERN "C" {
79 #endif /* __cplusplus */
80
81 \f
82 /*****************************************************************************
83  *                          RGU INTERFACE
84  ****************************************************************************/
85 /**
86  * @brief Handler for bind confirmation from MAC.
87  *
88  * @details
89  *    This function handles the bind confirmation received from MAC. If the 
90  *    bind was successful changes the state of the SAP to RLC_SAP_BND 
91  *    else RLC_SAP_CFG. Sends an alarm to LM in any case
92  *
93  * @param[in] pst     Post structure
94  * @param[in] suId    Service User ID
95  * @param[in] status  Status whether the bind was successful or not
96  *
97  * @return  S16
98  *    -# ROK 
99  *    -# RFAILED 
100  *
101 */
102 #ifdef ANSI
103 S16 RlcLiRguBndCfm
104 (
105 Pst    *pst,   
106 SuId   suId, 
107 U8     status 
108 )
109 #else
110 S16 RlcLiRguBndCfm (pst, suId, status)
111 Pst    *pst; 
112 SuId   suId;
113 U8     status;
114 #endif
115 {
116    U16          event;     /* Event */
117    U16          cause;     /* Cause */
118    RlcRguSapCb   *rguSap;   /* RGU SAP Control Block */
119    RlcCb         *tRlcCb;
120
121    TRC3(RlcLiRguBndCfm)
122
123 #if (ERRCLASS & ERRCLS_INT_PAR)
124    if (pst->dstInst >= MAX_RLC_INSTANCES)
125    {
126       return  (RFAILED);
127    }
128 #endif
129    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
130
131    RLOG2(L_DEBUG,"RlcLiRguBndCfm(suId(%d), status(%d)", suId, status);
132
133 #if (ERRCLASS & ERRCLS_INT_PAR)
134    if (tRlcCb->init.cfgDone != TRUE)
135    {
136       RLOG0(L_FATAL,"General configuration not done");
137       
138       RLC_SEND_SAPID_ALARM(tRlcCb,suId,LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_STATE);
139
140       return RFAILED;
141    }
142
143    if ((suId >= tRlcCb->genCfg.maxRguSaps) || (suId < 0))
144    {
145       RLOG0(L_ERROR, "Invalid suId");
146       
147       RLC_SEND_SAPID_ALARM(tRlcCb,suId, LKW_EVENT_LI_BND_CFM, LCM_CAUSE_INV_SUID);
148
149       return RFAILED;
150    }
151 #endif /* ERRCLASS & ERRCLS_INT_PAR */
152
153    rguSap = (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL) ?
154             &(tRlcCb->u.dlCb->rguDlSap[suId]) : &(tRlcCb->u.ulCb->rguUlSap[suId]);
155
156    RLOG1(L_DEBUG, "RlcLiRguBndCfm: For RGU SAP state=%d", rguSap->state)
157
158    switch (rguSap->state)
159    {
160       case RLC_SAP_BINDING:
161       {
162          rlcStopTmr (tRlcCb,(PTR)rguSap, RLC_EVT_WAIT_BNDCFM);
163
164          rguSap->retryCnt = 0;
165           
166          if (status == CM_BND_OK)
167          {
168             rguSap->state = RLC_SAP_BND;
169             event = LCM_EVENT_BND_OK;
170             cause = LKW_CAUSE_SAP_BNDENB;
171          }
172          else
173          {
174             rguSap->state = RLC_SAP_CFG;
175             event = LCM_EVENT_BND_FAIL;
176             cause = LKW_CAUSE_UNKNOWN;
177          }
178
179          break;
180       }
181       default:
182          event = LKW_EVENT_RGU_BND_CFM;
183          cause = LCM_CAUSE_INV_STATE;
184          break;
185    }
186
187    /* Send an alarm with proper event and cause */
188    RLC_SEND_SAPID_ALARM(tRlcCb, suId, event, cause);
189
190    return (ROK);
191 } /* RlcLiRguBndCfm */
192
193 int   rlcDDatIndRcvd;
194 int   rlcCDatIndRcvd;
195 /**
196  * @brief Handler to process PDU received from MAC for common logical channels. 
197  *
198  * @details
199  *    This function receives the PDU from MAC for common logical channels
200  *    does checks before handing over the PDU to the TM module
201  *
202  * @param[in] pst     Post structure
203  * @param[in] suId    Service User ID
204  * @param[in] datInd  Data Indication Information 
205  *
206  * @return  S16
207  *    -# ROK 
208  *    -# RFAILED 
209  *
210 */
211 uint8_t rlcProcCommLcUlData(Pst *pst, SuId suId, RguCDatIndInfo *datInd)
212 {
213    RlcUlRbCb   *rbCb; 
214    RlcCb       *tRlcCb; 
215
216    rlcCDatIndRcvd++;
217
218 #if (ERRCLASS & ERRCLS_INT_PAR)
219    if (pst->dstInst >= MAX_RLC_INSTANCES)
220    {
221       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguCDatIndInfo));
222       return RFAILED;
223    }
224 #endif
225
226    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
227
228 #if (ERRCLASS & ERRCLS_DEBUG)
229    if (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_DL)
230    {
231       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguCDatIndInfo));
232       return RFAILED;
233    }
234 #endif
235
236    /* kw006.201 ccpu00120058, Added array boundary condition check */
237 #if (ERRCLASS & ERRCLS_DEBUG)
238    if(RLC_MAX_LCH_PER_CELL <= datInd->lcId)
239    {
240       DU_LOG("\nRLC : rlcProcCommLcUlData : Invalid LcId [%d], Max is [%d]",\
241          datInd->lcId, RLC_MAX_LCH_PER_CELL);
242       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguCDatIndInfo));
243       return RFAILED;
244    }
245 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
246
247    /* Fetch RbCb from lcId */
248    rlcDbmFetchUlRbCbFromLchId(tRlcCb, datInd->rnti, datInd->cellId, datInd->lcId, &rbCb);
249    if (!rbCb)
250    {
251       DU_LOG("\nRLC : rlcProcCommLcUlData : LcId [%d] not found",
252          datInd->lcId);
253       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguCDatIndInfo));
254       return RFAILED;
255    }
256
257    /* Dispatch to TM Module */
258 #ifdef CCPU_OPT
259    rlcTmmRcvFrmMac(tRlcCb, rbCb, datInd->rnti, datInd->pdu);
260 #else /* CCPU_OPT */
261    rlcTmmRcvFrmMac(tRlcCb, rbCb, datInd->pdu);
262 #endif /* CCPU_OPT */
263
264    RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguCDatIndInfo));
265
266    return (ROK);
267 } /* rlcProcCommLcUlData */
268
269 /**
270  * @brief Handler to process PDU received from MAC for 
271  *        dedicated logical channels. 
272  *
273  * @details
274  *    This function receives the PDU from MAC for one or more dedicated 
275  *    logical channels and passes it to the UTL module for further processing
276  *
277  * @param[in] pst     Post structure
278  * @param[in] suId    Service User ID
279  * @param[in] datInd  Data Indication Information 
280  *
281  * @return  S16
282  *    -# ROK 
283  *    -# RFAILED 
284  *
285 */
286  
287 uint8_t rlcProcDedLcUlData(Pst *pst, SuId suId, RguDDatIndInfo *datInd)
288 {
289    rlcDDatIndRcvd++;
290 #if (ERRCLASS & ERRCLS_INT_PAR)
291    if (pst->dstInst >= MAX_RLC_INSTANCES)
292    {
293        RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguDDatIndInfo));
294        return RFAILED;
295    }
296 #endif
297
298 #if (ERRCLASS & ERRCLS_DEBUG)
299    if (((RlcCb*)RLC_GET_RLCCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_DL)
300    {
301        DU_LOG("\nRLC : rlcProcDedLcUlData : suId(%d))recieved in DL Inst", suId);
302        RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguDDatIndInfo));
303        return RFAILED;
304    }
305 #endif
306    rlcUtlRcvFrmMac(RLC_GET_RLCCB(pst->dstInst),datInd);
307 #ifndef SS_RBUF 
308 #ifdef SS_LOCKLESS_MEMORY
309    RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguDDatIndInfo));
310 #else
311    RLC_PST_FREE(RLC_MEM_REGION_UL, RLC_POOL, datInd, sizeof(RguDDatIndInfo));
312 #endif
313 #endif
314
315    return ROK;
316 } /* rlcProcDedLcUlData */
317
318 /**
319  * @brief Handler for trigerring the data transfer from RLC to MAC
320  *        for common logical channels.
321  *
322  * @details
323  *    This function receives the size of the PDU to be transmitted
324  *    and acts as a trigger for forming PDU and sending it to MAC. 
325  *
326  * @param[in] pst       Post structure
327  * @param[in] suId      Service User ID
328  * @param[in] staInd    Status Indication Information for Common Logical 
329  *                      Channels
330  *
331  * @return  S16
332  *    -# ROK 
333  *    -# RFAILED 
334  *
335 */ 
336 uint8_t rlcProcCommLcSchedRpt(Pst *pst, SuId suId, RguCStaIndInfo *staInd)
337 {
338    RlcDlRbCb   *rbCb;  
339    RlcCb       *tRlcCb;
340
341 #if (ERRCLASS & ERRCLS_INT_PAR)
342    if (pst->dstInst >= MAX_RLC_INSTANCES)
343    {
344       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
345       return  (RFAILED);
346    }
347 #endif
348
349    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
350
351 #if (ERRCLASS & ERRCLS_INT_PAR)
352    if ((suId >= tRlcCb->genCfg.maxRguSaps) || (suId < 0))
353    {
354       DU_LOG("\nRLC: rlcProcCommLcSchedRpt: Invalid RGU suId %d\n", suId);
355       return RFAILED; 
356    }
357    if (tRlcCb->genCfg.rlcMode == LKW_RLC_MODE_UL)
358    {
359        DU_LOG("\nRLC: rlcProcCommLcSchedRpt: Received in RLC UL CELLID:%d",
360              staInd->cellId);
361        RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
362        return RFAILED;
363    }
364 #endif
365
366    rbCb = NULLP;
367
368    /* kw006.201 ccpu00120058, added boundary condition check */
369 #if (ERRCLASS & ERRCLS_DEBUG)
370    if(RLC_MAX_LCH_PER_CELL < staInd->lcId)
371    {
372       DU_LOG("\nRLC: rlcProcCommLcSchedRpt: Invalid LcId, Max is [%d] CELLID:%d",
373          RLC_MAX_LCH_PER_CELL, staInd->cellId);
374       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
375       return RFAILED;
376    }
377 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
378    /* Fertch RbCb from lcId */
379    rlcDbmFetchDlRbCbFromLchId(tRlcCb,0, staInd->cellId, staInd->lcId, &rbCb);
380    if(!rbCb)                                               
381    {
382       DU_LOG("\nRLC: rlcProcCommLcSchedRpt: LcId [%d] not found CELLID:%d",
383          staInd->lcId, staInd->cellId);
384       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
385       return RFAILED;
386    }
387
388    /* Dispatch to TM Module */
389    rbCb->transId = staInd->transId;
390    rlcTmmSendToMac(tRlcCb, suId, rbCb, staInd);
391 #ifndef SS_RBUF
392 #ifdef SS_LOCKLESS_MEMORY
393    RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
394 #else
395    RLC_PST_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
396 #endif
397 #else
398    RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguCStaIndInfo));
399 #endif
400    return ROK;
401 } /* rlcProcCommLcSchedRpt */
402
403 /**
404  * @brief Handler for trigerring the data transfer from RLC to MAC
405  *        for dedicated logical channels.
406  *
407  * @details
408  *    This function receives the size of the PDUs to be transmitted to
409  *    MAC via one or more dedicated logical channels and acts as a trigger
410  *    for forming PDUs and sending them to MAC. 
411  *
412  * @param[in] pst       Post structure
413  * @param[in] suId      Service User ID
414  * @param[in] staInd    Status Indication Information for Dedicated Logical 
415  *                      Channels
416  *
417  * @return  S16
418  *    -# ROK 
419  *    -# RFAILED 
420  *
421 */ 
422 uint8_t rlcProcDedLcSchedRpt(Pst *pst, SuId suId, RguDStaIndInfo *staInd)
423 {
424    RlcCb        *gCb;
425
426 #if (ERRCLASS & ERRCLS_INT_PAR)
427    if (pst->dstInst >= MAX_RLC_INSTANCES)
428    {
429       RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguDStaIndInfo));
430       return RFAILED;
431    }
432 #endif
433
434    gCb = RLC_GET_RLCCB(pst->dstInst);
435
436 #if (ERRCLASS & ERRCLS_INT_PAR)
437    if (((RlcCb*)RLC_GET_RLCCB(pst->dstInst))->genCfg.rlcMode == LKW_RLC_MODE_UL)
438    {
439        DU_LOG("\nRLC: rlcProcDedLcSchedRpt: Received in RLC UL ");
440        RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguDStaIndInfo));
441        return RFAILED;
442    }
443    if ((suId >= gCb->genCfg.maxRguSaps) || (suId < 0))
444    {
445       DU_LOG("\nRLC: rlcProcDedLcSchedRpt: Invalid RGU suId %d\n", suId);
446       return (RFAILED); 
447    }
448 #endif
449    rlcUtlSendToMac(gCb, suId, staInd);
450
451    /* kw002.201 :Freeing from proper region */
452    RLC_SHRABL_STATIC_BUF_FREE(RLC_MEM_REGION_DL, RLC_POOL, staInd, sizeof(RguDStaIndInfo));
453    return ROK;
454 } /* rlcProcDedLcSchedRpt */
455
456 /**
457  * @brief Handler for handling the flow cntrl Ind from MAC
458  *  to RLC      
459  *
460  * @details
461  *   This function receives the flow control indication from
462  *   MAC and calls rlcUtlTrigPdbFlowCntrl
463  *
464  * @param[in] pst       Post structure
465  * @param[in] suId      Service User ID
466  * @param[in] flowCntrlInd flow control Indication Information 
467  *           from MAC  
468  *
469  * @return  S16
470  *    -# ROK 
471  *    -# RFAILED 
472  *
473 */ 
474 #ifdef ANSI
475 S16 RlcLiRguFlowCntrlInd
476 (
477 Pst              *pst,  
478 SuId             suId,
479 RguFlowCntrlInd *flowCntrlInd
480 )
481 #else
482 S16 RlcLiRguFlowCntrlInd(pst, suId, flowCntrlInd)
483 Pst              *pst; 
484 SuId             suId; 
485 RguFlowCntrlInd  *flowCntrlInd; 
486 #endif
487 {
488    RlcCb       *tRlcCb; 
489    RlcDlRbCb   *rbCb = NULLP;
490    U32        idx;
491    U32        lcIdx;
492
493    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
494    for (idx = 0; idx < flowCntrlInd->numUes; idx++)
495    {
496       for (lcIdx = 0; lcIdx < flowCntrlInd->ueFlowCntrlInfo[idx].numLcs; lcIdx++)  
497       {
498          RguLcFlowCntrlInfo *lcInfo = &(flowCntrlInd->ueFlowCntrlInfo[idx].lcInfo[lcIdx]); 
499          rlcDbmFetchDlRbCbFromLchId(tRlcCb, flowCntrlInd->ueFlowCntrlInfo[idx].ueId, flowCntrlInd->cellId, lcInfo->lcId, &rbCb);
500          if (rbCb)
501          {
502            
503             if (lcInfo->pktAdmitCnt == 0) /* Special case */
504             {
505                rlcUtlTrigPdbFlowCntrl(tRlcCb, rbCb, lcInfo->pktAdmitCnt);
506                continue;
507             }
508             if (rbCb->mode == CM_LTE_MODE_AM)
509             {
510                if ((rbCb->m.amDl.retxLst.count != 0) || 
511                    ((rbCb->m.amDl.bo == 0) || 
512                     (rbCb->m.amDl.bo < lcInfo->maxBo4FlowCtrl)))
513                {
514                   continue;
515                }
516             }
517             else /* UM */
518             {
519                if ((rbCb->m.umDl.bo == 0) ||
520                    (rbCb->m.umDl.bo < lcInfo->maxBo4FlowCtrl))
521                {
522                   continue;
523                }
524             }
525             rlcUtlTrigPdbFlowCntrl(tRlcCb, rbCb, lcInfo->pktAdmitCnt);
526          }
527       }
528    }
529    return ROK;
530 }
531 /* kw005.201 added support for L2 Measurement */
532 #ifdef LTE_L2_MEAS
533 \f
534 /**
535  *
536  * @brief  
537  *
538  *        Handler for indicating the Harq Status of the data sent.
539  *
540  * @b Description:
541  *
542  *        This function receives the harq status of the data sent to MAC.
543  *        This information is used for two things.
544  *        1. Computing the UuLoss of UM
545  *        2. Computing the DL Delay for UM and AM.
546  *
547  *  @param[in] pst     -   Post structure  
548  *  @param[in] suId    -   Service User ID
549  *  @param[in] staInd  -   Harq Status Indication Information. 
550  *
551  *  @return  S16
552  *      -# ROK 
553  *      -# RFAILED
554  *
555  */
556 #ifdef ANSI
557 S16 RlcLiRguHqStaInd
558 (
559 Pst                *pst, 
560 SuId               suId,
561 RguHarqStatusInd   *staInd 
562 )
563 #else
564 S16 RlcLiRguHqStaInd(pst,suId,staInd)
565 Pst                *pst;  
566 SuId               suId; 
567 RguHarqStatusInd   *staInd;
568 #endif
569 {
570
571    RlcUeKey   ueKey;
572    S16       ret; 
573    RlcDlUeCb    *ueCb;
574    U8        tbIdx;
575    RlcCb       *tRlcCb; 
576
577    TRC3(RlcLiRguHqStaInd)
578
579    tRlcCb = RLC_GET_RLCCB(pst->dstInst);
580    ueKey.cellId = staInd->cellId;
581    ueKey.ueId   = staInd->ueId;
582
583    ret = rlcDbmFetchDlUeCb(tRlcCb, ueKey.ueId, ueKey.cellId, &ueCb);
584    if (ret != ROK )
585    {
586       return RFAILED;
587    }
588
589    /*Call rlcUtlProcHarqInd as many times as number of Tbs present*/
590    for ( tbIdx = 0; tbIdx < staInd->numTbs; tbIdx++)
591    {
592       rlcUtlProcHarqInd(tRlcCb, staInd, ueCb, tbIdx);
593    }
594
595    return (ROK);
596 } /* RlcLiRguHqStaInd */
597 #endif /* LTE_L2_MEAS */
598
599 #ifdef __cplusplus
600 }
601 #endif /* __cplusplus */
602
603 /********************************************************************30**
604          End of file
605 **********************************************************************/