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.slot = datReqInfo->tm.tmg.slot;
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 */
216 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
219 /* (Sfn,slot) at which the message should be transmitted is
220 * validated with alloted (sfn,slot)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 slot 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,slot 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 slot = staInd->pagingTimingInfo.slot;
242 sfn = (staInd->transId >> 8) & 0x3FF;
243 slot = staInd->transId & 0xFF;
247 * tm.slot - current slot
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 ((slot + TFU_DELTA) >= 10)
259 sfn = (sfn + 1)%1024;
262 if ((sdu->mode.tm.sfn != sfn) ||
263 (sdu->mode.tm.slot != ((slot+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 slot %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 dlData,(Size)sizeof(RlcMacData));
380 #if (ERRCLASS & ERRCLS_ADD_RES)
381 if ( dlData == 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 dlData->timeToTx.sfn = sdu->mode.tm.sfn;
392 dlData->timeToTx.slot = sdu->mode.tm.slot;
393 dlData->cellId = rbCb->rlcId.cellId;
394 dlData->rnti = sdu->mode.tm.rnti;
396 dlData->pduInfo[0].commCh = TRUE;
397 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
398 dlData->pduInfo[0].pduBuf = sdu->mBuf;
400 /* kw005.201 ccpu00117318, updating the statistics */
401 gCb->genSts.bytesSent += sdu->sduSz;
402 gCb->genSts.pdusSent++;
404 kwUtlIncrementKwuStsSduTx(gCb->u.dlCb->kwuDlSap + rbCb->kwuSapId);
406 /* remove SDU from queue */
408 cmLListDelFrm(&(rbCb->m.tm.sduQ),
410 KW_FREE(gCb,sdu, sizeof(KwSdu));
412 /* If trace flag is enabled send the trace indication */
413 if(gCb->init.trc == TRUE)
415 /* Populate the trace params */
416 kwLmmSendTrc(gCb,EVTRLCDLDAT, NULLP);
419 RlcMacSendDlData(&(gCb->u.dlCb->rguDlSap[suId].pst),
420 gCb->u.dlCb->rguDlSap[suId].spId,
428 * Handler to process the re-establishment request received from the upper
432 * This function empties the SDU queue for the RB in the downlink.
434 * @param[in] gCb RLC Instance Control Block
435 * @param[in] rbCb RB control block.
441 PUBLIC Void kwDlTmmReEstablish
447 PUBLIC Void kwDlTmmReEstablish(gCb,rbCb)
452 TRC2(kwDlTmmReEstablish)
455 #ifdef LTE_L2_MEAS_RLC
456 kwUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
458 kwUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
466 * Handler to send Status Response to the lower layer.
469 * This function is used to the BO to the lower layer after receiving a data
470 * request from the upper layer.
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.
483 PRIVATE Void kwTmmSndStaRsp
488 KwuDatReqInfo *datReqInfo
491 PRIVATE Void kwTmmSndStaRsp(rbCb,bo,datReqInfo)
495 KwuDatReqInfo *datReqInfo;
498 // RguCStaRspInfo *staRspInfo; /* Status Response Information */
499 RlcMacBOStatus *boStatus; /* Buffer occupancy status information */
500 KwRguSapCb *rguSap; /* SAP Information */
505 rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
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 )
513 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
514 "Memory Allocation failed UEID:%d CELLID:%d",
519 #endif /* ERRCLASS & ERRCLS_ADD_RES */
521 boStatus->cellId = rbCb->rlcId.cellId;
522 boStatus->rnti = rbCb->rlcId.ueId;
523 boStatus->commCh = TRUE;
524 boStatus->lcId = rbCb->lch.lChId;
527 /* If trace flag is enabled send the trace indication */
528 if(gCb->init.trc == TRUE)
530 /* Populate the trace params */
531 kwLmmSendTrc(gCb, EVTRLCBOSTA, NULLP);
534 RlcMacSendBOStatus(&rguSap->pst, rguSap->spId, boStatus);
543 /********************************************************************30**
545 **********************************************************************/