730f3656b404acc3c2fbdaec77402ffc628cc29d
[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    RguCDatReqInfo   *cDatReqInfo;   /* Data Request Information */
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                         cDatReqInfo,(Size)sizeof(RguCDatReqInfo));
380 #if (ERRCLASS & ERRCLS_ADD_RES)
381    if ( cDatReqInfo == 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 #ifdef CCPU_OPT
391    if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||  
392         rbCb->lch.lChType == CM_LTE_LCH_PCCH )
393    {
394       cDatReqInfo->u.timeToTx.sfn = sdu->mode.tm.sfn;
395       cDatReqInfo->u.timeToTx.subframe = sdu->mode.tm.subframe;
396 #ifdef EMTC_ENABLE
397        if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
398        {
399          cDatReqInfo->pnb = sdu->mode.tm.pnb; 
400        }
401 #endif
402    }
403    else
404    {
405       cDatReqInfo->u.rnti = sdu->mode.tm.rnti;
406    }
407 #endif 
408    cDatReqInfo->pdu = sdu->mBuf; 
409    cDatReqInfo->transId = rbCb->transId;
410    cDatReqInfo->cellId  = rbCb->rlcId.cellId;
411    cDatReqInfo->lcId   = rbCb->lch.lChId; 
412    cDatReqInfo->lcType = rbCb->lch.lChType; 
413
414    /* kw005.201 ccpu00117318, updating the statistics */
415    gCb->genSts.bytesSent += sdu->sduSz;
416    gCb->genSts.pdusSent++;
417
418    kwUtlIncrementKwuStsSduTx(gCb->u.dlCb->kwuDlSap + rbCb->kwuSapId);   
419
420    /* remove SDU from queue */ 
421    sdu->mBuf = NULLP;
422    cmLListDelFrm(&(rbCb->m.tm.sduQ),
423                  &sdu->lstEnt); 
424    KW_FREE(gCb,sdu, sizeof(KwSdu));
425
426    /* If trace flag is enabled send the trace indication */
427    if(gCb->init.trc == TRUE)
428    {
429       /* Populate the trace params */
430       kwLmmSendTrc(gCb,EVTRGUCDATREQ, NULLP);
431    }
432    KwLiRguCDatReq (&(gCb->u.dlCb->rguDlSap[suId].pst), 
433                    gCb->u.dlCb->rguDlSap[suId].spId, 
434                    cDatReqInfo);
435    
436    RETVOID;
437 }
438
439 /**
440  *
441  * @brief 
442  *    Handler to process the re-establishment request received from the upper 
443  *    layer. 
444  *
445  * @details
446  *    This function empties the SDU queue for the RB in the downlink.
447  *            
448  * @param[in] gCb   RLC Instance Control Block 
449  * @param[in] rbCb  RB control block. 
450  *
451  * @return  S16
452  *    -# ROK 
453  */
454 #ifdef ANSI
455 PUBLIC Void kwDlTmmReEstablish
456 (
457 KwCb       *gCb,
458 KwDlRbCb   *rbCb    
459 )
460 #else
461 PUBLIC Void kwDlTmmReEstablish(gCb,rbCb)
462 KwCb       *gCb;
463 KwDlRbCb   *rbCb;     
464 #endif
465 {
466    TRC2(kwDlTmmReEstablish)
467
468
469 #ifdef LTE_L2_MEAS_RLC
470    kwUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
471 #else
472    kwUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
473 #endif
474    
475    RETVOID;
476 }
477 /**
478  *
479  * @brief 
480  *    Handler to send Status Response to the lower layer.
481  *
482  * @details
483  *    This function is used to the BO to the lower layer after receiving a data
484  *    request from the upper layer. 
485  *            
486  * @param[in] gCb          RLC Instance Control Block 
487  * @param[in] rbCb         RB control block. 
488  * @param[in] bo           Buffer Occupancy 
489  * @param[in] datReqInfo   Data Request Information.
490  *
491  * @return  S16
492  *    -# ROK 
493  *    -# RFAILED 
494  */
495
496 #ifdef ANSI
497 PRIVATE Void kwTmmSndStaRsp
498 (
499 KwCb            *gCb,
500 KwDlRbCb        *rbCb,                 
501 MsgLen          bo,                    
502 KwuDatReqInfo   *datReqInfo         
503 )
504 #else
505 PRIVATE Void kwTmmSndStaRsp(rbCb,bo,datReqInfo)
506 KwCb            *gCb;
507 KwDlRbCb        *rbCb;               
508 MsgLen          bo;                
509 KwuDatReqInfo   *datReqInfo;   
510 #endif
511 {
512    RguCStaRspInfo   *staRspInfo;   /* Status Response Information */
513    KwRguSapCb       *rguSap;       /* SAP Information */
514
515    TRC3(kwTmmSndStaRsp)
516
517
518    rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
519
520    KW_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.region,
521                        gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.pool,
522                        staRspInfo,sizeof(RguCStaRspInfo));
523 #if (ERRCLASS & ERRCLS_ADD_RES)
524    if ( staRspInfo == NULLP )
525    {
526       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
527             "Memory Allocation failed UEID:%d CELLID:%d",
528             rbCb->rlcId.ueId,
529             rbCb->rlcId.cellId);   
530       RETVOID;
531    }
532 #endif /* ERRCLASS & ERRCLS_ADD_RES */
533    staRspInfo->bo = bo;
534    staRspInfo->cellId = rbCb->rlcId.cellId;
535    staRspInfo->lcId   = rbCb->lch.lChId;
536    staRspInfo->lcType = rbCb->lch.lChType;
537 #ifdef CCPU_OPT    
538    if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
539         rbCb->lch.lChType == CM_LTE_LCH_PCCH )
540    {
541       staRspInfo->u.timeToTx.sfn      = datReqInfo->tm.tmg.sfn;
542       staRspInfo->u.timeToTx.subframe = datReqInfo->tm.tmg.subframe;
543 #ifdef EMTC_ENABLE
544       if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
545       {
546          staRspInfo->emtcDiReason = datReqInfo->emtcDiReason;
547          staRspInfo->pnb = datReqInfo->pnb;
548       }
549 #endif
550    }
551    else if ( rbCb->lch.lChType == CM_LTE_LCH_CCCH )
552    {
553        staRspInfo->u.rnti = datReqInfo->tm.rnti;
554    }
555 #endif
556
557    /* If trace flag is enabled send the trace indication */
558    if(gCb->init.trc == TRUE)
559    {
560       /* Populate the trace params */
561       kwLmmSendTrc(gCb,EVTRGUCSTARSP, NULLP);
562    }
563
564    KwLiRguCStaRsp(&rguSap->pst,rguSap->spId,staRspInfo);
565
566    RETVOID;
567
568
569 #ifdef _cplusplus
570 }
571 #endif
572 /*@}*/
573 /********************************************************************30**
574          End of file
575 **********************************************************************/