RLC-MAC Interface APIs and Memory configuration Changes
[o-du/l2.git] / src / 5gnrrlc / kw_tmm_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
19 /**********************************************************************
20
21      Name:     LTE-RLC Layer 
22   
23      Type:     C file
24   
25      Desc:     Source code for RLC Transparent mode assembly and
26                reassembly.This file contains following functions
27                 
28                   --kwTmmQSdu
29                   --kwTmmSndToLi
30                   --kwTmmRcvFrmLi
31                   --kwTmmReEstablish 
32
33      File:     kw_tmm_dl.c
34
35 **********************************************************************/
36 static const char* RLOG_MODULE_NAME="TMM";
37 static int RLOG_MODULE_ID=2048;
38 static int RLOG_FILE_ID=200;
39 /** 
40  * @file kw_tmm_dl.c
41  * @brief RLC Transparent Mode module
42 */
43 \f
44 /* header (.h) include files */
45 #include "envopt.h"        /* environment options */
46 #include "envdep.h"        /* environment dependent */
47 #include "envind.h"        /* environment independent */
48
49 #include "gen.h"           /* general */
50 #include "ssi.h"           /* system services */
51 #include "cm5.h"           /* common timer defines */
52 #include "cm_tkns.h"       /* common tokens defines */
53 #include "cm_mblk.h"       /* common memory allocation library defines */
54 #include "cm_llist.h"      /* common link list  defines  */
55 #include "cm_hash.h"       /* common hash list  defines */
56 #include "cm_lte.h"        /* common LTE defines */
57 #include "lkw.h"           /* LKW defines */
58 #include "ckw.h"           /* CKW defines */
59 #include "kwu.h"           /* KWU defines */
60 #include "rgu.h"           /* RGU defines */
61 #include "kw_env.h"        /* RLC environment options */
62
63 #include "kw.h"            /* RLC defines */
64 #include "kw_err.h"            /* RLC defines */
65 #include "kw_udx.h"
66 #include "kw_dl.h"
67
68 /* extern (.x) include files */
69 #include "gen.x"           /* general */
70 #include "ssi.x"           /* system services */
71
72 #include "cm5.x"           /* common timer library */
73 #include "cm_tkns.x"       /* common tokens */
74 #include "cm_mblk.x"       /* common memory allocation */
75 #include "cm_llist.x"      /* common link list */
76 #include "cm_hash.x"       /* common hash list */
77 #include "cm_lte.x"        /* common LTE includes */
78 #include "cm_lib.x"        /* common memory allocation library */
79 #include "lkw.x"           /* LKW */
80 #include "ckw.x"           /* CKW */
81 #include "kwu.x"           /* KWU */
82 #include "rgu.x"           /* RGU */
83
84 #include "kw.x"
85 #include "kw_udx.x"
86 #include "kw_dl.x"
87
88 #define KW_MODULE (KW_DBGMASK_TM | KW_DBGMASK_DL)
89
90 PRIVATE Void kwTmmSndStaRsp ARGS((KwCb *gCb, KwDlRbCb *rbCb, 
91                                  MsgLen bo, KwuDatReqInfo *datReqInfo));
92 extern U32 rgMacGT ;  
93 /** @addtogroup tmmode */
94 /*@{*/
95
96 /**
97  * @brief 
98  *    Handler to queue the SDU in the SDU queue and update BO and report it to
99  *    the lower layer.
100  *
101  * @details 
102  *    This function is used to queue the received SDU in the SDU queue 
103  *    maintained in the radio bearer control block. After queuing the SDU, BO 
104  *    is updated and is reported to the lower layer. 
105  *            
106  *  @param[in] rbCb         RB control block. 
107  *  @param[in] datReqInfo   Data Request Information.
108  *  @param[in] mBuf         SDU Buffer.
109  *
110  *  @return  S16
111  *      -# ROK 
112  *      -# RFAILED 
113  */
114 #ifdef ANSI
115 PUBLIC Void kwTmmQSdu
116 (
117 KwCb            *gCb,
118 KwDlRbCb        *rbCb,      
119 KwuDatReqInfo   *datReqInfo, 
120 Buffer          *mBuf       
121 )
122 #else
123 PUBLIC Void kwTmmQSdu(gCb,rbCb,datReqInfo,mBuf)
124 KwCb            *gCb;
125 KwDlRbCb        *rbCb;       
126 KwuDatReqInfo   *datReqInfo;  
127 Buffer          *mBuf;         
128 #endif
129 {
130    KwSdu   *sdu;              
131  
132    TRC2(kwTmmQSdu) 
133
134
135    KW_ALLOC(gCb,sdu,sizeof(KwSdu));
136 #if (ERRCLASS & ERRCLS_ADD_RES)
137    if ( sdu == NULLP )
138    {
139       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
140             "Memory Allocation failed UEID:%d CELLID:%d",   
141             rbCb->rlcId.ueId,
142             rbCb->rlcId.cellId);   
143       RETVOID;
144    }
145 #endif /* ERRCLASS & ERRCLS_ADD_RES */
146 #ifdef CCPU_OPT   
147    if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || 
148         rbCb->lch.lChType == CM_LTE_LCH_PCCH )
149    {
150       sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
151       sdu->mode.tm.subframe = datReqInfo->tm.tmg.subframe;
152 #ifdef EMTC_ENABLE
153      if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
154      {
155         sdu->mode.tm.pnb = datReqInfo->pnb;
156      }
157 #endif
158    }
159    else
160    {
161       sdu->mode.tm.rnti = datReqInfo->tm.rnti;
162    }
163 #endif
164    sdu->arrTime = rgMacGT;
165    SFndLenMsg(mBuf,&sdu->sduSz); 
166    sdu->mBuf = mBuf;
167    
168    cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));  
169    sdu->lstEnt.node = (PTR)sdu; 
170
171    kwTmmSndStaRsp(gCb, rbCb, sdu->sduSz, datReqInfo); 
172    RETVOID;
173 }
174
175 /**
176 * @brief 
177 *    Handler to form a pdu and send it to the lower layer.
178
179 * @details 
180 *    This function forms one pdu from the first SDU in the SDU queue and sends 
181 *    it to the lower layer.
182 *             
183 * @param[in] gCb     RLC Instance Control Block
184 * @param[in] rbCb    RB control block. 
185 * @param[in] staInd  Status Indication of common logical channel 
186 *
187 * @return  S16
188 *    -# ROK 
189 *    -# RFAILED         
190 */
191 #ifdef ANSI
192 PUBLIC Void kwTmmSndToLi
193 (
194 KwCb             *gCb,
195 SuId             suId,
196 KwDlRbCb         *rbCb,              
197 RguCStaIndInfo   *staInd
198 )
199 #else
200 PUBLIC Void kwTmmSndToLi(gCb, suId, rbCb, staInd)
201 KwCb             *gCb;
202 SuId             suId;
203 KwDlRbCb         *rbCb;             
204 RguCStaIndInfo   *staInd;
205 #endif
206 {
207    CmLList          *node;          /* Current Link List Node */
208    KwSdu            *sdu;           /* SDU */
209    RlcMacData       *dlData;
210    S16   timeDiff = 0;
211    Ticks curTime  = 0;
212
213    TRC2(kwTmmSndToLi)
214
215
216    CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ), 
217                        node);
218
219    /* (Sfn,subframe) at which the message should be transmitted is 
220     * validated with alloted (sfn,subframe)in the MAC layer */
221    while (node != NULLP)
222    {
223       sdu = (KwSdu *)(node->node);
224       if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
225             rbCb->lch.lChType == CM_LTE_LCH_PCCH )
226       {
227          U16 sfn, subframe;
228          /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
229 #ifdef EMTC_ENABLE
230          /* As part of CATM feature cross subframe scheduling is implemented , so there is some delta(currently 2)
231             between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra 
232             information is provided in staInd, so that sfn,subframe should calculate from paging Timing information 
233             in case of EMTC paging, instead of transId */
234          if(staInd->isEmtcPaging)
235          {
236             sfn      = staInd->pagingTimingInfo.sfn;
237             subframe = staInd->pagingTimingInfo.subframe;
238          }
239          else
240 #endif
241          {
242             sfn = (staInd->transId >> 8) & 0x3FF;
243             subframe = staInd->transId & 0xFF;
244          }
245
246          /* Table
247           * tm.subframe - current subframe 
248           * 0,sfn        7,sfn-1
249           * 4,sfn        1,sfn
250           * 5,sfn        2,sfn
251           * 9,sfn        6,sfn
252           */
253          /* MS_FIX: syed Incorrect sfn determination. 
254           * Take care of SFN wraparound. TODO: It is better for RLC
255           * not to be aware of SCH DELTAs. So we should look for 
256           * sending actual transmission time to RLC. */
257          if ((subframe + TFU_DELTA) >= 10)
258          {
259             sfn = (sfn + 1)%1024;
260          }
261
262          if ((sdu->mode.tm.sfn != sfn) ||
263                (sdu->mode.tm.subframe != ((subframe+TFU_DELTA)%10)))
264          {
265             node = node->next;
266             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
267                   "Releasing SDU of RNTI = %d for RNTI = %d UEID:%d CELLID:%d",
268                   sdu->mode.tm.rnti, 
269                   staInd->rnti,
270                   rbCb->rlcId.ueId,
271                   rbCb->rlcId.cellId);   
272             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
273                   "sfn %d subframe %d  UEID:%d CELLID:%d",
274                   sfn, 
275                   subframe,
276                   rbCb->rlcId.ueId,
277                   rbCb->rlcId.cellId);   
278             cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
279             KW_FREE_BUF(sdu->mBuf);
280             KW_FREE(gCb, sdu, sizeof(KwSdu));
281          }
282          else
283          {
284             break;
285          }
286       }
287       else
288       {
289          curTime = rgMacGT;
290          if (curTime < sdu->arrTime)
291          {
292             timeDiff = (10240 - sdu->arrTime) + curTime;
293          }
294          else
295          {
296             timeDiff = curTime - sdu->arrTime;
297          }
298          RLOG_ARG4(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId,
299                "TMM: TmSdu Sta Indication received for Rnti %d Sdu Rnti %d "
300                " UEID:%d CELLID:%d", 
301                staInd->rnti, 
302                sdu->mode.tm.rnti,
303                rbCb->rlcId.ueId,
304                rbCb->rlcId.cellId);   
305          RLOG_ARG4(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId,
306                "TMM: TmSdu Sta Indication received : timeDiff %d SduQCnt %lu"
307                " UEID:%d CELLID:%d", 
308                timeDiff, 
309                rbCb->m.tm.sduQ.count,
310                rbCb->rlcId.ueId,
311                rbCb->rlcId.cellId);   
312          if (timeDiff > 40)
313          {
314             /* Memory leak needs to be fixed */
315             node = node->next;
316             RLOG_ARG3(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId,
317                   " timeDiff greater than 40, so deleting the Sdu %u "
318                   " UEID:%d CELLID:%d", 
319                   sdu->mode.tm.rnti,
320                   rbCb->rlcId.ueId,
321                   rbCb->rlcId.cellId);   
322             cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
323             KW_FREE_BUF(sdu->mBuf);
324             KW_FREE(gCb, sdu, sizeof(KwSdu));
325             continue;
326          }
327
328          if (sdu->mode.tm.rnti != staInd->rnti)
329          {
330             /* Memory leak needs to be fixed */
331             node = node->next;
332             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, 
333                   "TMM: Searching for Rnti %d Skipping Sdu for Rnti %d"
334                   " UEID:%d CELLID:%d", 
335                   staInd->rnti,
336                   sdu->mode.tm.rnti, 
337                   rbCb->rlcId.ueId,
338                   rbCb->rlcId.cellId);   
339             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, 
340                   " timeDiff %d sdu->arrTime %d"
341                   " UEID:%d CELLID:%d", 
342                   timeDiff, 
343                   sdu->arrTime,
344                   rbCb->rlcId.ueId,
345                   rbCb->rlcId.cellId);   
346             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, 
347                   "curTime %d SduQCnt %lu and continuing"
348                   " UEID:%d CELLID:%d", 
349                    curTime, 
350                    rbCb->m.tm.sduQ.count,
351                   rbCb->rlcId.ueId,
352                   rbCb->rlcId.cellId);   
353             continue;
354          }
355          else
356          {
357             RLOG_ARG3(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId,
358                   "TMM: TmSdu found %u UEID:%d CELLID:%d",
359                   sdu->mode.tm.rnti,
360                   rbCb->rlcId.ueId,
361                   rbCb->rlcId.cellId);   
362             break;
363          }
364       }
365
366    }
367    if ( node == NULLP )
368    {
369       RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
370                "SDU not found TM Queue is empty UEID:%d CELLID:%d",
371                rbCb->rlcId.ueId,
372                rbCb->rlcId.cellId);   
373       RETVOID;
374    }
375    sdu = (KwSdu *)node->node;
376
377     KW_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap[suId].pst.region,
378                         gCb->u.dlCb->rguDlSap[suId].pst.pool,
379                         dlData,(Size)sizeof(RlcMacData));
380 #if (ERRCLASS & ERRCLS_ADD_RES)
381    if ( dlData == NULLP )
382    {
383       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
384             "Memory Allocation failed UEID:%d CELLID:%d",   
385                rbCb->rlcId.ueId,
386                rbCb->rlcId.cellId);   
387       RETVOID; 
388    }
389 #endif /* ERRCLASS & ERRCLS_ADD_RES */
390
391    dlData->timeToTx.sfn = sdu->mode.tm.sfn;
392    dlData->timeToTx.subframe = sdu->mode.tm.subframe;
393    dlData->cellId = rbCb->rlcId.cellId;
394    dlData->rnti = sdu->mode.tm.rnti;
395    dlData->nmbPdu = 1;
396    dlData->pduInfo[0].commCh = TRUE;
397    dlData->pduInfo[0].lcId = rbCb->lch.lChId;
398    dlData->pduInfo[0].pduBuf =  sdu->mBuf;
399
400    /* kw005.201 ccpu00117318, updating the statistics */
401    gCb->genSts.bytesSent += sdu->sduSz;
402    gCb->genSts.pdusSent++;
403
404    kwUtlIncrementKwuStsSduTx(gCb->u.dlCb->kwuDlSap + rbCb->kwuSapId);   
405
406    /* remove SDU from queue */ 
407    sdu->mBuf = NULLP;
408    cmLListDelFrm(&(rbCb->m.tm.sduQ),
409                  &sdu->lstEnt); 
410    KW_FREE(gCb,sdu, sizeof(KwSdu));
411
412    /* If trace flag is enabled send the trace indication */
413    if(gCb->init.trc == TRUE)
414    {
415       /* Populate the trace params */
416       kwLmmSendTrc(gCb,EVTRLCDLDAT, NULLP);
417    }
418    
419    RlcMacSendDlData(&(gCb->u.dlCb->rguDlSap[suId].pst),
420                    gCb->u.dlCb->rguDlSap[suId].spId,
421                    dlData);
422    RETVOID;
423 }
424
425 /**
426  *
427  * @brief 
428  *    Handler to process the re-establishment request received from the upper 
429  *    layer. 
430  *
431  * @details
432  *    This function empties the SDU queue for the RB in the downlink.
433  *            
434  * @param[in] gCb   RLC Instance Control Block 
435  * @param[in] rbCb  RB control block. 
436  *
437  * @return  S16
438  *    -# ROK 
439  */
440 #ifdef ANSI
441 PUBLIC Void kwDlTmmReEstablish
442 (
443 KwCb       *gCb,
444 KwDlRbCb   *rbCb    
445 )
446 #else
447 PUBLIC Void kwDlTmmReEstablish(gCb,rbCb)
448 KwCb       *gCb;
449 KwDlRbCb   *rbCb;     
450 #endif
451 {
452    TRC2(kwDlTmmReEstablish)
453
454
455 #ifdef LTE_L2_MEAS_RLC
456    kwUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
457 #else
458    kwUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
459 #endif
460    
461    RETVOID;
462 }
463 /**
464  *
465  * @brief 
466  *    Handler to send Status Response to the lower layer.
467  *
468  * @details
469  *    This function is used to the BO to the lower layer after receiving a data
470  *    request from the upper layer. 
471  *            
472  * @param[in] gCb          RLC Instance Control Block 
473  * @param[in] rbCb         RB control block. 
474  * @param[in] bo           Buffer Occupancy 
475  * @param[in] datReqInfo   Data Request Information.
476  *
477  * @return  S16
478  *    -# ROK 
479  *    -# RFAILED 
480  */
481
482 #ifdef ANSI
483 PRIVATE Void kwTmmSndStaRsp
484 (
485 KwCb            *gCb,
486 KwDlRbCb        *rbCb,                 
487 MsgLen          bo,                    
488 KwuDatReqInfo   *datReqInfo         
489 )
490 #else
491 PRIVATE Void kwTmmSndStaRsp(rbCb,bo,datReqInfo)
492 KwCb            *gCb;
493 KwDlRbCb        *rbCb;               
494 MsgLen          bo;                
495 KwuDatReqInfo   *datReqInfo;   
496 #endif
497 {
498 //   RguCStaRspInfo   *staRspInfo;   /* Status Response Information */
499    RlcMacBOStatus   *boStatus;      /* Buffer occupancy status information */
500    KwRguSapCb       *rguSap;       /* SAP Information */
501
502    TRC3(kwTmmSndStaRsp)
503
504
505    rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
506
507    KW_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.region,
508                        gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.pool,
509                        boStatus, sizeof(RguCStaRspInfo));
510 #if (ERRCLASS & ERRCLS_ADD_RES)
511    if ( boStatus == NULLP )
512    {
513       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
514             "Memory Allocation failed UEID:%d CELLID:%d",
515             rbCb->rlcId.ueId,
516             rbCb->rlcId.cellId);   
517       RETVOID;
518    }
519 #endif /* ERRCLASS & ERRCLS_ADD_RES */
520
521    boStatus->cellId = rbCb->rlcId.cellId;
522    boStatus->rnti = rbCb->rlcId.ueId;
523    boStatus->commCh = TRUE;
524    boStatus->lcId = rbCb->lch.lChId;
525    boStatus->bo = bo;
526
527    /* If trace flag is enabled send the trace indication */
528    if(gCb->init.trc == TRUE)
529    {
530       /* Populate the trace params */
531       kwLmmSendTrc(gCb, EVTRLCBOSTA, NULLP);
532    }
533
534    RlcMacSendBOStatus(&rguSap->pst, rguSap->spId, boStatus);
535
536    RETVOID;
537
538
539 #ifdef _cplusplus
540 }
541 #endif
542 /*@}*/
543 /********************************************************************30**
544          End of file
545 **********************************************************************/