1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /**********************************************************************
25 Desc: Source code for RLC Transparent mode assembly and
26 reassembly.This file contains following functions
35 **********************************************************************/
36 static const char* RLOG_MODULE_NAME="TMM";
37 static int RLOG_MODULE_ID=2048;
38 static int RLOG_FILE_ID=200;
41 * @brief RLC Transparent Mode module
44 /* header (.h) include files */
45 #include "envopt.h" /* environment options */
46 #include "envdep.h" /* environment dependent */
47 #include "envind.h" /* environment independent */
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 */
63 #include "kw.h" /* RLC defines */
64 #include "kw_err.h" /* RLC defines */
68 /* extern (.x) include files */
69 #include "gen.x" /* general */
70 #include "ssi.x" /* system services */
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 */
88 #define KW_MODULE (KW_DBGMASK_TM | KW_DBGMASK_DL)
90 PRIVATE Void kwTmmSndStaRsp ARGS((KwCb *gCb, KwDlRbCb *rbCb,
91 MsgLen bo, KwuDatReqInfo *datReqInfo));
93 /** @addtogroup tmmode */
98 * Handler to queue the SDU in the SDU queue and update BO and report it to
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.
106 * @param[in] rbCb RB control block.
107 * @param[in] datReqInfo Data Request Information.
108 * @param[in] mBuf SDU Buffer.
115 PUBLIC Void kwTmmQSdu
119 KwuDatReqInfo *datReqInfo,
123 PUBLIC Void kwTmmQSdu(gCb,rbCb,datReqInfo,mBuf)
126 KwuDatReqInfo *datReqInfo;
135 KW_ALLOC(gCb,sdu,sizeof(KwSdu));
136 #if (ERRCLASS & ERRCLS_ADD_RES)
139 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
140 "Memory Allocation failed UEID:%d CELLID:%d",
145 #endif /* ERRCLASS & ERRCLS_ADD_RES */
147 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
148 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
150 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
151 sdu->mode.tm.subframe = datReqInfo->tm.tmg.subframe;
153 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
155 sdu->mode.tm.pnb = datReqInfo->pnb;
161 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
164 sdu->arrTime = rgMacGT;
165 SFndLenMsg(mBuf,&sdu->sduSz);
168 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
169 sdu->lstEnt.node = (PTR)sdu;
171 kwTmmSndStaRsp(gCb, rbCb, sdu->sduSz, datReqInfo);
177 * Handler to form a pdu and send it to the lower layer.
180 * This function forms one pdu from the first SDU in the SDU queue and sends
181 * it to the lower layer.
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
192 PUBLIC Void kwTmmSndToLi
197 RguCStaIndInfo *staInd
200 PUBLIC Void kwTmmSndToLi(gCb, suId, rbCb, staInd)
204 RguCStaIndInfo *staInd;
207 CmLList *node; /* Current Link List Node */
208 KwSdu *sdu; /* SDU */
209 RguCDatReqInfo *cDatReqInfo; /* Data Request Information */
216 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
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)
223 sdu = (KwSdu *)(node->node);
224 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
225 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
228 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
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)
236 sfn = staInd->pagingTimingInfo.sfn;
237 subframe = staInd->pagingTimingInfo.subframe;
242 sfn = (staInd->transId >> 8) & 0x3FF;
243 subframe = staInd->transId & 0xFF;
247 * tm.subframe - current subframe
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)
259 sfn = (sfn + 1)%1024;
262 if ((sdu->mode.tm.sfn != sfn) ||
263 (sdu->mode.tm.subframe != ((subframe+TFU_DELTA)%10)))
266 RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
267 "Releasing SDU of RNTI = %d for RNTI = %d UEID:%d CELLID:%d",
272 RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
273 "sfn %d subframe %d UEID:%d CELLID:%d",
278 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
279 KW_FREE_BUF(sdu->mBuf);
280 KW_FREE(gCb, sdu, sizeof(KwSdu));
290 if (curTime < sdu->arrTime)
292 timeDiff = (10240 - sdu->arrTime) + curTime;
296 timeDiff = curTime - sdu->arrTime;
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",
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",
309 rbCb->m.tm.sduQ.count,
314 /* Memory leak needs to be fixed */
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",
322 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
323 KW_FREE_BUF(sdu->mBuf);
324 KW_FREE(gCb, sdu, sizeof(KwSdu));
328 if (sdu->mode.tm.rnti != staInd->rnti)
330 /* Memory leak needs to be fixed */
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",
339 RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
340 " timeDiff %d sdu->arrTime %d"
341 " UEID:%d CELLID:%d",
346 RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
347 "curTime %d SduQCnt %lu and continuing"
348 " UEID:%d CELLID:%d",
350 rbCb->m.tm.sduQ.count,
357 RLOG_ARG3(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId,
358 "TMM: TmSdu found %u UEID:%d CELLID:%d",
369 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
370 "SDU not found TM Queue is empty UEID:%d CELLID:%d",
375 sdu = (KwSdu *)node->node;
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 )
383 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
384 "Memory Allocation failed UEID:%d CELLID:%d",
389 #endif /* ERRCLASS & ERRCLS_ADD_RES */
391 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
392 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
394 cDatReqInfo->u.timeToTx.sfn = sdu->mode.tm.sfn;
395 cDatReqInfo->u.timeToTx.subframe = sdu->mode.tm.subframe;
397 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
399 cDatReqInfo->pnb = sdu->mode.tm.pnb;
405 cDatReqInfo->u.rnti = sdu->mode.tm.rnti;
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;
414 /* kw005.201 ccpu00117318, updating the statistics */
415 gCb->genSts.bytesSent += sdu->sduSz;
416 gCb->genSts.pdusSent++;
418 kwUtlIncrementKwuStsSduTx(gCb->u.dlCb->kwuDlSap + rbCb->kwuSapId);
420 /* remove SDU from queue */
422 cmLListDelFrm(&(rbCb->m.tm.sduQ),
424 KW_FREE(gCb,sdu, sizeof(KwSdu));
426 /* If trace flag is enabled send the trace indication */
427 if(gCb->init.trc == TRUE)
429 /* Populate the trace params */
430 kwLmmSendTrc(gCb,EVTRGUCDATREQ, NULLP);
432 KwLiRguCDatReq (&(gCb->u.dlCb->rguDlSap[suId].pst),
433 gCb->u.dlCb->rguDlSap[suId].spId,
442 * Handler to process the re-establishment request received from the upper
446 * This function empties the SDU queue for the RB in the downlink.
448 * @param[in] gCb RLC Instance Control Block
449 * @param[in] rbCb RB control block.
455 PUBLIC Void kwDlTmmReEstablish
461 PUBLIC Void kwDlTmmReEstablish(gCb,rbCb)
466 TRC2(kwDlTmmReEstablish)
469 #ifdef LTE_L2_MEAS_RLC
470 kwUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
472 kwUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
480 * Handler to send Status Response to the lower layer.
483 * This function is used to the BO to the lower layer after receiving a data
484 * request from the upper layer.
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.
497 PRIVATE Void kwTmmSndStaRsp
502 KwuDatReqInfo *datReqInfo
505 PRIVATE Void kwTmmSndStaRsp(rbCb,bo,datReqInfo)
509 KwuDatReqInfo *datReqInfo;
512 RguCStaRspInfo *staRspInfo; /* Status Response Information */
513 KwRguSapCb *rguSap; /* SAP Information */
518 rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
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 )
526 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
527 "Memory Allocation failed UEID:%d CELLID:%d",
532 #endif /* ERRCLASS & ERRCLS_ADD_RES */
534 staRspInfo->cellId = rbCb->rlcId.cellId;
535 staRspInfo->lcId = rbCb->lch.lChId;
536 staRspInfo->lcType = rbCb->lch.lChType;
538 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
539 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
541 staRspInfo->u.timeToTx.sfn = datReqInfo->tm.tmg.sfn;
542 staRspInfo->u.timeToTx.subframe = datReqInfo->tm.tmg.subframe;
544 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
546 staRspInfo->emtcDiReason = datReqInfo->emtcDiReason;
547 staRspInfo->pnb = datReqInfo->pnb;
551 else if ( rbCb->lch.lChType == CM_LTE_LCH_CCCH )
553 staRspInfo->u.rnti = datReqInfo->tm.rnti;
557 /* If trace flag is enabled send the trace indication */
558 if(gCb->init.trc == TRUE)
560 /* Populate the trace params */
561 kwLmmSendTrc(gCb,EVTRGUCSTARSP, NULLP);
564 KwLiRguCStaRsp(&rguSap->pst,rguSap->spId,staRspInfo);
573 /********************************************************************30**
575 **********************************************************************/