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 **********************************************************************/
38 * @brief RLC Transparent Mode module
41 /* header (.h) include files */
42 #include "common_def.h"
43 #include "lkw.h" /* LKW defines */
44 #include "ckw.h" /* CKW defines */
45 #include "kwu.h" /* KWU defines */
46 #include "rgu.h" /* RGU defines */
47 #include "kw_env.h" /* RLC environment options */
49 #include "kw.h" /* RLC defines */
50 #include "kw_err.h" /* RLC defines */
54 /* extern (.x) include files */
55 #include "lkw.x" /* LKW */
56 #include "ckw.x" /* CKW */
57 #include "kwu.x" /* KWU */
58 #include "rgu.x" /* RGU */
63 #include "rlc_utils.h"
64 #include "rlc_mac_inf.h"
65 #include "rlc_lwr_inf_api.h"
67 #define RLC_MODULE (RLC_DBGMASK_TM | RLC_DBGMASK_DL)
69 static Void rlcTmmSendBoSta ARGS((RlcCb *gCb, RlcDlRbCb *rbCb,
70 MsgLen bo, KwuDatReqInfo *datReqInfo));
72 /** @addtogroup tmmode */
77 * Handler to queue the SDU in the SDU queue and update BO and report it to
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.
85 * @param[in] rbCb RB control block.
86 * @param[in] datReqInfo Data Request Information.
87 * @param[in] mBuf SDU Buffer.
98 KwuDatReqInfo *datReqInfo,
102 Void rlcTmmQSdu(gCb,rbCb,datReqInfo,mBuf)
105 KwuDatReqInfo *datReqInfo;
111 RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
112 #if (ERRCLASS & ERRCLS_ADD_RES)
115 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
116 "Memory Allocation failed UEID:%d CELLID:%d",
121 #endif /* ERRCLASS & ERRCLS_ADD_RES */
123 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
124 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
126 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
127 sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
129 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
131 sdu->mode.tm.pnb = datReqInfo->pnb;
137 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
140 sdu->arrTime = rgMacGT;
141 SFndLenMsg(mBuf,&sdu->sduSz);
144 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
145 sdu->lstEnt.node = (PTR)sdu;
147 rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo);
153 * Handler to form a pdu and send it to the lower layer.
156 * This function forms one pdu from the first SDU in the SDU queue and sends
157 * it to the lower layer.
159 * @param[in] gCb RLC Instance Control Block
160 * @param[in] rbCb RB control block.
161 * @param[in] staInd Status Indication of common logical channel
167 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
170 CmLList *node; /* Current Link List Node */
171 RlcSdu *sdu; /* SDU */
175 int16_t timeDiff = 0;
178 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
181 /* (Sfn,slot) at which the message should be transmitted is
182 * validated with alloted (sfn,slot)in the MAC layer */
183 while (node != NULLP)
185 sdu = (RlcSdu *)(node->node);
186 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
187 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
190 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
192 /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
193 between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra
194 information is provided in staInd, so that sfn,slot should calculate from paging Timing information
195 in case of EMTC paging, instead of transId */
196 if(staInd->isEmtcPaging)
198 sfn = staInd->pagingTimingInfo.sfn;
199 slot = staInd->pagingTimingInfo.slot;
204 sfn = (staInd->transId >> 8) & 0x3FF;
205 slot = staInd->transId & 0xFF;
209 * tm.slot - current slot
215 /* MS_FIX: syed Incorrect sfn determination.
216 * Take care of SFN wraparound. TODO: It is better for RLC
217 * not to be aware of SCH DELTAs. So we should look for
218 * sending actual transmission time to RLC. */
219 if ((slot + TFU_DELTA) >= 10)
221 sfn = (sfn + 1)%1024;
224 if ((sdu->mode.tm.sfn != sfn) ||
225 (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
228 DU_LOG("\nRLC: rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
229 UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
231 DU_LOG("\nRLC: rlcTmmSendToMac: sfn %d slot %d UEID:%d CELLID:%d",
232 sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
233 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
234 RLC_FREE_BUF(sdu->mBuf);
235 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
245 if (curTime < sdu->arrTime)
247 timeDiff = (10240 - sdu->arrTime) + curTime;
251 timeDiff = curTime - sdu->arrTime;
253 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
254 for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti,
255 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
256 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
257 timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
258 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
261 /* Memory leak needs to be fixed */
263 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff greater than 40, so deleting\
264 the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
266 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
267 RLC_FREE_BUF(sdu->mBuf);
268 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
272 if (sdu->mode.tm.rnti != staInd->rnti)
274 /* Memory leak needs to be fixed */
276 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
277 Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti,
278 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
279 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d",
280 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
281 DU_LOG("\nRLC: rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
282 " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
288 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
289 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
297 DU_LOG("\nRLC: rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
298 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
301 sdu = (RlcSdu *)node->node;
303 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
304 dlData,(Size)sizeof(RlcData));
305 #if (ERRCLASS & ERRCLS_ADD_RES)
306 if ( dlData == NULLP )
308 DU_LOG("\nRLC: rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",
309 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
312 #endif /* ERRCLASS & ERRCLS_ADD_RES */
314 dlData->slotInfo.sfn = sdu->mode.tm.sfn;
315 dlData->slotInfo.slot = sdu->mode.tm.slot;
316 dlData->cellId = rbCb->rlcId.cellId;
317 dlData->rnti = sdu->mode.tm.rnti;
319 dlData->pduInfo[0].commCh = TRUE;
320 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
322 /* Copy Message to fixed buffer to send */
323 ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
324 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
325 dlData->pduInfo[0].pduBuf, pduLen);
326 if (dlData->pduInfo[0].pduBuf == NULLP )
328 DU_LOG("Memory allocation failed");
331 ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
332 dlData->pduInfo[0].pduBuf, (MsgLen *)©Len);
333 dlData->pduInfo[0].pduLen = pduLen;
336 ODU_PUT_MSG_BUF(sdu->mBuf);
338 /* kw005.201 ccpu00117318, updating the statistics */
339 gCb->genSts.bytesSent += sdu->sduSz;
340 gCb->genSts.pdusSent++;
342 rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);
344 /* remove SDU from queue */
346 cmLListDelFrm(&(rbCb->m.tm.sduQ),
348 RLC_FREE(gCb,sdu, sizeof(RlcSdu));
350 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
351 * changes in rguSap->pst */
352 memset(&pst, 0, sizeof(Pst));
353 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
355 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
357 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
358 dlData->pduInfo[0].pduLen);
359 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
368 * Handler to process the re-establishment request received from the upper
372 * This function empties the SDU queue for the RB in the downlink.
374 * @param[in] gCb RLC Instance Control Block
375 * @param[in] rbCb RB control block.
381 Void rlcDlTmmReEstablish
387 Void rlcDlTmmReEstablish(gCb,rbCb)
393 #ifdef LTE_L2_MEAS_RLC
394 rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
396 rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
404 * Handler to send Status Response to the lower layer.
407 * This function is used to the BO to the lower layer after receiving a data
408 * request from the upper layer.
410 * @param[in] gCb RLC Instance Control Block
411 * @param[in] rbCb RB control block.
412 * @param[in] bo Buffer Occupancy
413 * @param[in] datReqInfo Data Request Information.
420 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, KwuDatReqInfo *datReqInfo)
422 Pst pst; /* Post structure */
423 RlcBoStatus *boStatus; /* Buffer occupancy status information */
425 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
426 boStatus, sizeof(RlcBoStatus));
427 if ( boStatus == NULLP )
429 DU_LOG("Memory Allocation failed UEID:%d CELLID:%d",\
430 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
434 boStatus->cellId = rbCb->rlcId.cellId;
435 boStatus->ueIdx = rbCb->rlcId.ueId;
436 boStatus->commCh = TRUE;
437 boStatus->lcId = rbCb->lch.lChId;
440 /* If trace flag is enabled send the trace indication */
441 if(gCb->init.trc == TRUE)
443 /* Populate the trace params */
444 rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
447 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
448 * changes in rguSap->pst */
449 memset(&pst, 0, sizeof(Pst));
450 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
452 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
454 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
464 /********************************************************************30**
466 **********************************************************************/