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