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 PRIVATE 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;
114 RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
115 #if (ERRCLASS & ERRCLS_ADD_RES)
118 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
119 "Memory Allocation failed UEID:%d CELLID:%d",
124 #endif /* ERRCLASS & ERRCLS_ADD_RES */
126 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
127 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
129 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
130 sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
132 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
134 sdu->mode.tm.pnb = datReqInfo->pnb;
140 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
143 sdu->arrTime = rgMacGT;
144 SFndLenMsg(mBuf,&sdu->sduSz);
147 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
148 sdu->lstEnt.node = (PTR)sdu;
150 rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo);
156 * Handler to form a pdu and send it to the lower layer.
159 * This function forms one pdu from the first SDU in the SDU queue and sends
160 * it to the lower layer.
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
170 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
173 CmLList *node; /* Current Link List Node */
174 RlcSdu *sdu; /* SDU */
178 int16_t timeDiff = 0;
181 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
184 /* (Sfn,slot) at which the message should be transmitted is
185 * validated with alloted (sfn,slot)in the MAC layer */
186 while (node != NULLP)
188 sdu = (RlcSdu *)(node->node);
189 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
190 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
193 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
195 /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
196 between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra
197 information is provided in staInd, so that sfn,slot should calculate from paging Timing information
198 in case of EMTC paging, instead of transId */
199 if(staInd->isEmtcPaging)
201 sfn = staInd->pagingTimingInfo.sfn;
202 slot = staInd->pagingTimingInfo.slot;
207 sfn = (staInd->transId >> 8) & 0x3FF;
208 slot = staInd->transId & 0xFF;
212 * tm.slot - current slot
218 /* MS_FIX: syed Incorrect sfn determination.
219 * Take care of SFN wraparound. TODO: It is better for RLC
220 * not to be aware of SCH DELTAs. So we should look for
221 * sending actual transmission time to RLC. */
222 if ((slot + TFU_DELTA) >= 10)
224 sfn = (sfn + 1)%1024;
227 if ((sdu->mode.tm.sfn != sfn) ||
228 (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
231 DU_LOG("\nRLC: rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
232 UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
234 DU_LOG("\nRLC: rlcTmmSendToMac: sfn %d slot %d UEID:%d CELLID:%d",
235 sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
236 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
237 RLC_FREE_BUF(sdu->mBuf);
238 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
248 if (curTime < sdu->arrTime)
250 timeDiff = (10240 - sdu->arrTime) + curTime;
254 timeDiff = curTime - sdu->arrTime;
256 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
257 for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti,
258 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
259 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
260 timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
261 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
264 /* Memory leak needs to be fixed */
266 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff greater than 40, so deleting\
267 the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
269 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
270 RLC_FREE_BUF(sdu->mBuf);
271 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
275 if (sdu->mode.tm.rnti != staInd->rnti)
277 /* Memory leak needs to be fixed */
279 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
280 Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti,
281 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
282 DU_LOG("\nRLC: rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d",
283 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
284 DU_LOG("\nRLC: rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
285 " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
291 DU_LOG("\nRLC: rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
292 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
300 DU_LOG("\nRLC: rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
301 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
304 sdu = (RlcSdu *)node->node;
306 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
307 dlData,(Size)sizeof(RlcData));
308 #if (ERRCLASS & ERRCLS_ADD_RES)
309 if ( dlData == NULLP )
311 DU_LOG("\nRLC: rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",
312 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
315 #endif /* ERRCLASS & ERRCLS_ADD_RES */
317 dlData->slotInfo.sfn = sdu->mode.tm.sfn;
318 dlData->slotInfo.slot = sdu->mode.tm.slot;
319 dlData->cellId = rbCb->rlcId.cellId;
320 dlData->rnti = sdu->mode.tm.rnti;
322 dlData->pduInfo[0].commCh = TRUE;
323 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
325 /* Copy Message to fixed buffer to send */
326 ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
327 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
328 dlData->pduInfo[0].pduBuf, pduLen);
329 if (dlData->pduInfo[0].pduBuf == NULLP )
331 DU_LOG("Memory allocation failed");
334 ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
335 dlData->pduInfo[0].pduBuf, (MsgLen *)©Len);
336 dlData->pduInfo[0].pduLen = pduLen;
339 ODU_PUT_MSG_BUF(sdu->mBuf);
341 /* kw005.201 ccpu00117318, updating the statistics */
342 gCb->genSts.bytesSent += sdu->sduSz;
343 gCb->genSts.pdusSent++;
345 rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);
347 /* remove SDU from queue */
349 cmLListDelFrm(&(rbCb->m.tm.sduQ),
351 RLC_FREE(gCb,sdu, sizeof(RlcSdu));
353 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
354 * changes in rguSap->pst */
355 memset(&pst, 0, sizeof(Pst));
356 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
358 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
360 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
361 dlData->pduInfo[0].pduLen);
362 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
371 * Handler to process the re-establishment request received from the upper
375 * This function empties the SDU queue for the RB in the downlink.
377 * @param[in] gCb RLC Instance Control Block
378 * @param[in] rbCb RB control block.
384 Void rlcDlTmmReEstablish
390 Void rlcDlTmmReEstablish(gCb,rbCb)
395 TRC2(rlcDlTmmReEstablish)
398 #ifdef LTE_L2_MEAS_RLC
399 rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
401 rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
409 * Handler to send Status Response to the lower layer.
412 * This function is used to the BO to the lower layer after receiving a data
413 * request from the upper layer.
415 * @param[in] gCb RLC Instance Control Block
416 * @param[in] rbCb RB control block.
417 * @param[in] bo Buffer Occupancy
418 * @param[in] datReqInfo Data Request Information.
425 void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, KwuDatReqInfo *datReqInfo)
427 Pst pst; /* Post structure */
428 RlcBoStatus *boStatus; /* Buffer occupancy status information */
430 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
431 boStatus, sizeof(RlcBoStatus));
432 if ( boStatus == NULLP )
434 DU_LOG("Memory Allocation failed UEID:%d CELLID:%d",\
435 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
439 boStatus->cellId = rbCb->rlcId.cellId;
440 boStatus->ueIdx = rbCb->rlcId.ueId;
441 boStatus->commCh = TRUE;
442 boStatus->lcId = rbCb->lch.lChId;
445 /* If trace flag is enabled send the trace indication */
446 if(gCb->init.trc == TRUE)
448 /* Populate the trace params */
449 rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
452 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
453 * changes in rguSap->pst */
454 memset(&pst, 0, sizeof(Pst));
455 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
457 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
459 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
469 /********************************************************************30**
471 **********************************************************************/