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.
97 KwuDatReqInfo *datReqInfo,
103 RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
104 #if (ERRCLASS & ERRCLS_ADD_RES)
107 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
108 "Memory Allocation failed UEID:%d CELLID:%d",
113 #endif /* ERRCLASS & ERRCLS_ADD_RES */
115 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
116 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
118 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
119 sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
121 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
123 sdu->mode.tm.pnb = datReqInfo->pnb;
129 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
132 sdu->arrTime = rgMacGT;
133 SFndLenMsg(mBuf,&sdu->sduSz);
136 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
137 sdu->lstEnt.node = (PTR)sdu;
139 rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo);
145 * Handler to form a pdu and send it to the lower layer.
148 * This function forms one pdu from the first SDU in the SDU queue and sends
149 * it to the lower layer.
151 * @param[in] gCb RLC Instance Control Block
152 * @param[in] rbCb RB control block.
153 * @param[in] staInd Status Indication of common logical channel
159 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
162 CmLList *node; /* Current Link List Node */
163 RlcSdu *sdu; /* SDU */
167 int16_t timeDiff = 0;
170 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
173 /* (Sfn,slot) at which the message should be transmitted is
174 * validated with alloted (sfn,slot)in the MAC layer */
175 while (node != NULLP)
177 sdu = (RlcSdu *)(node->node);
178 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
179 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
182 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
184 /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
185 between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra
186 information is provided in staInd, so that sfn,slot should calculate from paging Timing information
187 in case of EMTC paging, instead of transId */
188 if(staInd->isEmtcPaging)
190 sfn = staInd->pagingTimingInfo.sfn;
191 slot = staInd->pagingTimingInfo.slot;
196 sfn = (staInd->transId >> 8) & 0x3FF;
197 slot = staInd->transId & 0xFF;
201 * tm.slot - current slot
207 /* MS_FIX: syed Incorrect sfn determination.
208 * Take care of SFN wraparound. TODO: It is better for RLC
209 * not to be aware of SCH DELTAs. So we should look for
210 * sending actual transmission time to RLC. */
211 if ((slot + TFU_DELTA) >= 10)
213 sfn = (sfn + 1)%1024;
216 if ((sdu->mode.tm.sfn != sfn) ||
217 (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
220 DU_LOG("\nRLC: rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
221 UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
223 DU_LOG("\nRLC: rlcTmmSendToMac: sfn %d slot %d UEID:%d CELLID:%d",
224 sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
225 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
226 RLC_FREE_BUF(sdu->mBuf);
227 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
237 if (curTime < sdu->arrTime)
239 timeDiff = (10240 - sdu->arrTime) + curTime;
243 timeDiff = curTime - sdu->arrTime;
245 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
246 for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti,
247 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
248 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
249 timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
250 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
253 /* Memory leak needs to be fixed */
255 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff greater than 40, so deleting\
256 the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
258 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
259 RLC_FREE_BUF(sdu->mBuf);
260 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
264 if (sdu->mode.tm.rnti != staInd->rnti)
266 /* Memory leak needs to be fixed */
268 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
269 Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti,
270 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
271 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d",
272 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
273 DU_LOG("\nRLC: rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
274 " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
280 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
281 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
289 DU_LOG("\nRLC: rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
290 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
293 sdu = (RlcSdu *)node->node;
295 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
296 dlData,(Size)sizeof(RlcData));
297 #if (ERRCLASS & ERRCLS_ADD_RES)
298 if ( dlData == NULLP )
300 DU_LOG("\nRLC: rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",
301 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
304 #endif /* ERRCLASS & ERRCLS_ADD_RES */
306 dlData->slotInfo.sfn = sdu->mode.tm.sfn;
307 dlData->slotInfo.slot = sdu->mode.tm.slot;
308 dlData->cellId = rbCb->rlcId.cellId;
309 dlData->rnti = sdu->mode.tm.rnti;
311 dlData->pduInfo[0].commCh = TRUE;
312 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
314 /* Copy Message to fixed buffer to send */
315 ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
316 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
317 dlData->pduInfo[0].pduBuf, pduLen);
318 if (dlData->pduInfo[0].pduBuf == NULLP )
320 DU_LOG("Memory allocation failed");
323 ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
324 dlData->pduInfo[0].pduBuf, (MsgLen *)©Len);
325 dlData->pduInfo[0].pduLen = pduLen;
328 ODU_PUT_MSG_BUF(sdu->mBuf);
330 /* kw005.201 ccpu00117318, updating the statistics */
331 gCb->genSts.bytesSent += sdu->sduSz;
332 gCb->genSts.pdusSent++;
334 rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);
336 /* remove SDU from queue */
338 cmLListDelFrm(&(rbCb->m.tm.sduQ),
340 RLC_FREE(gCb,sdu, sizeof(RlcSdu));
342 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
343 * changes in rguSap->pst */
344 memset(&pst, 0, sizeof(Pst));
345 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
347 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
349 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
350 dlData->pduInfo[0].pduLen);
351 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
360 * Handler to process the re-establishment request received from the upper
364 * This function empties the SDU queue for the RB in the downlink.
366 * @param[in] gCb RLC Instance Control Block
367 * @param[in] rbCb RB control block.
372 Void rlcDlTmmReEstablish
379 #ifdef LTE_L2_MEAS_RLC
380 rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
382 rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
390 * Handler to send Status Response to the lower layer.
393 * This function is used to the BO to the lower layer after receiving a data
394 * request from the upper layer.
396 * @param[in] gCb RLC Instance Control Block
397 * @param[in] rbCb RB control block.
398 * @param[in] bo Buffer Occupancy
399 * @param[in] datReqInfo Data Request Information.
406 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, KwuDatReqInfo *datReqInfo)
408 Pst pst; /* Post structure */
409 RlcBoStatus *boStatus; /* Buffer occupancy status information */
411 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
412 boStatus, sizeof(RlcBoStatus));
413 if ( boStatus == NULLP )
415 DU_LOG("Memory Allocation failed UEID:%d CELLID:%d",\
416 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
420 boStatus->cellId = rbCb->rlcId.cellId;
421 boStatus->ueIdx = rbCb->rlcId.ueId;
422 boStatus->commCh = TRUE;
423 boStatus->lcId = rbCb->lch.lChId;
426 /* If trace flag is enabled send the trace indication */
427 if(gCb->init.trc == TRUE)
429 /* Populate the trace params */
430 rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
433 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
434 * changes in rguSap->pst */
435 memset(&pst, 0, sizeof(Pst));
436 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
438 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
440 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
450 /********************************************************************30**
452 **********************************************************************/