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, RlcDatReqInfo *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 RlcDatReqInfo *datReqInfo,
103 RLC_ALLOC(gCb,sdu,sizeof(RlcSdu));
104 #if (ERRCLASS & ERRCLS_ADD_RES)
107 DU_LOG("\nERROR --> RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",
108 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
111 #endif /* ERRCLASS & ERRCLS_ADD_RES */
113 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
114 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
116 sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn;
117 sdu->mode.tm.slot = datReqInfo->tm.tmg.slot;
119 if(rbCb->lch.lChType == CM_LTE_LCH_PCCH)
121 sdu->mode.tm.pnb = datReqInfo->pnb;
127 sdu->mode.tm.rnti = datReqInfo->tm.rnti;
130 sdu->arrTime = rgMacGT;
131 SFndLenMsg(mBuf,&sdu->sduSz);
134 cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt));
135 sdu->lstEnt.node = (PTR)sdu;
137 rlcTmmSendBoSta(gCb, rbCb, sdu->sduSz, datReqInfo);
143 * Handler to form a pdu and send it to the lower layer.
146 * This function forms one pdu from the first SDU in the SDU queue and sends
147 * it to the lower layer.
149 * @param[in] gCb RLC Instance Control Block
150 * @param[in] rbCb RB control block.
151 * @param[in] staInd Status Indication of common logical channel
157 void rlcTmmSendToMac(RlcCb *gCb, SuId suId, RlcDlRbCb *rbCb, RguCStaIndInfo *staInd)
160 CmLList *node; /* Current Link List Node */
161 RlcSdu *sdu; /* SDU */
165 int16_t timeDiff = 0;
168 CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ),
171 /* (Sfn,slot) at which the message should be transmitted is
172 * validated with alloted (sfn,slot)in the MAC layer */
173 while (node != NULLP)
175 sdu = (RlcSdu *)(node->node);
176 if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH ||
177 rbCb->lch.lChType == CM_LTE_LCH_PCCH )
180 /* MS_FIX: syed sfn is of 10 bytes rather than 8 */
182 /* As part of CATM feature cross slot scheduling is implemented , so there is some delta(currently 2)
183 between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra
184 information is provided in staInd, so that sfn,slot should calculate from paging Timing information
185 in case of EMTC paging, instead of transId */
186 if(staInd->isEmtcPaging)
188 sfn = staInd->pagingTimingInfo.sfn;
189 slot = staInd->pagingTimingInfo.slot;
194 sfn = (staInd->transId >> 8) & 0x3FF;
195 slot = staInd->transId & 0xFF;
199 * tm.slot - current slot
205 /* MS_FIX: syed Incorrect sfn determination.
206 * Take care of SFN wraparound. TODO: It is better for RLC
207 * not to be aware of SCH DELTAs. So we should look for
208 * sending actual transmission time to RLC. */
209 if ((slot + TFU_DELTA) >= 10)
211 sfn = (sfn + 1)%1024;
214 if ((sdu->mode.tm.sfn != sfn) ||
215 (sdu->mode.tm.slot != ((slot+TFU_DELTA)%10)))
218 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: Releasing SDU of RNTI = %d for RNTI = %d \
219 UEID:%d CELLID:%d", sdu->mode.tm.rnti, staInd->rnti, rbCb->rlcId.ueId,
221 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: sfn %d slot %d UEID:%d CELLID:%d",
222 sfn, slot, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
223 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
224 ODU_PUT_MSG_BUF(sdu->mBuf);
225 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
235 if (curTime < sdu->arrTime)
237 timeDiff = (10240 - sdu->arrTime) + curTime;
241 timeDiff = curTime - sdu->arrTime;
243 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received \
244 for Rnti %d Sdu Rnti %d UEID:%d CELLID:%d", staInd->rnti,
245 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
246 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu Sta Indication received : \
247 timeDiff %d SduQCnt %d UEID:%d CELLID:%d", timeDiff, rbCb->m.tm.sduQ.count,
248 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
251 /* Memory leak needs to be fixed */
253 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: timeDiff greater than 40, so deleting\
254 the Sdu %u UEID:%d CELLID:%d", sdu->mode.tm.rnti, rbCb->rlcId.ueId,
256 cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt);
257 ODU_PUT_MSG_BUF(sdu->mBuf);
258 RLC_FREE(gCb, sdu, sizeof(RlcSdu));
262 if (sdu->mode.tm.rnti != staInd->rnti)
264 /* Memory leak needs to be fixed */
266 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: Searching for Rnti %d Skipping \
267 Sdu for Rnti %d UEID:%d CELLID:%d", staInd->rnti, sdu->mode.tm.rnti,
268 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
269 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: timeDiff %d sdu->arrTime %d UEID:%d CELLID:%d",
270 timeDiff, sdu->arrTime, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
271 DU_LOG("\nINFO --> RLC_DL : rlcTmmSendToMac: curTime %d SduQCnt %d and continuing"
272 " UEID:%d CELLID:%d", curTime, rbCb->m.tm.sduQ.count, rbCb->rlcId.ueId,
278 DU_LOG("\nDEBUG --> RLC_DL : rlcTmmSendToMac: TMM: TmSdu found %u UEID:%d CELLID:%d",
279 sdu->mode.tm.rnti, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
287 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: SDU not found TM Queue is empty UEID:%d CELLID:%d",
288 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
291 sdu = (RlcSdu *)node->node;
293 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
294 dlData,(Size)sizeof(RlcData));
295 #if (ERRCLASS & ERRCLS_ADD_RES)
296 if ( dlData == NULLP )
298 DU_LOG("\nERROR --> RLC_DL : rlcTmmSendToMac: Memory Allocation failed UEID:%d CELLID:%d",
299 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
302 #endif /* ERRCLASS & ERRCLS_ADD_RES */
304 dlData->slotInfo.sfn = sdu->mode.tm.sfn;
305 dlData->slotInfo.slot = sdu->mode.tm.slot;
306 dlData->cellId = rbCb->rlcId.cellId;
307 dlData->rnti = sdu->mode.tm.rnti;
309 dlData->pduInfo[0].commCh = TRUE;
310 dlData->pduInfo[0].lcId = rbCb->lch.lChId;
312 /* Copy Message to fixed buffer to send */
313 ODU_GET_MSG_LEN(sdu->mBuf, (MsgLen *)&pduLen);
314 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
315 dlData->pduInfo[0].pduBuf, pduLen);
316 if (dlData->pduInfo[0].pduBuf == NULLP )
318 DU_LOG("\nERROR --> RLC_DL : Memory allocation failed");
321 ODU_COPY_MSG_TO_FIX_BUF(sdu->mBuf, 0, pduLen, \
322 dlData->pduInfo[0].pduBuf, (MsgLen *)©Len);
323 dlData->pduInfo[0].pduLen = pduLen;
326 ODU_PUT_MSG_BUF(sdu->mBuf);
328 /* kw005.201 ccpu00117318, updating the statistics */
329 gCb->genSts.bytesSent += sdu->sduSz;
330 gCb->genSts.pdusSent++;
332 rlcUtlIncrementKwuStsSduTx(gCb->u.dlCb->rlcKwuDlSap + rbCb->k1wuSapId);
334 /* remove SDU from queue */
336 cmLListDelFrm(&(rbCb->m.tm.sduQ),
338 RLC_FREE(gCb,sdu, sizeof(RlcSdu));
340 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
341 * changes in rguSap->pst */
342 memset(&pst, 0, sizeof(Pst));
343 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
345 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
347 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[0].pduBuf, \
348 dlData->pduInfo[0].pduLen);
349 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
358 * Handler to process the re-establishment request received from the upper
362 * This function empties the SDU queue for the RB in the downlink.
364 * @param[in] gCb RLC Instance Control Block
365 * @param[in] rbCb RB control block.
370 Void rlcDlTmmReEstablish
377 #ifdef LTE_L2_MEAS_RLC
378 rlcUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ);
380 rlcUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ);
388 * Handler to send Status Response to the lower layer.
391 * This function is used to the BO to the lower layer after receiving a data
392 * request from the upper layer.
394 * @param[in] gCb RLC Instance Control Block
395 * @param[in] rbCb RB control block.
396 * @param[in] bo Buffer Occupancy
397 * @param[in] datReqInfo Data Request Information.
404 static void rlcTmmSendBoSta(RlcCb *gCb, RlcDlRbCb *rbCb, MsgLen bo, RlcDatReqInfo *datReqInfo)
406 Pst pst; /* Post structure */
407 RlcBoStatus *boStatus; /* Buffer occupancy status information */
409 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
410 boStatus, sizeof(RlcBoStatus));
411 if ( boStatus == NULLP )
413 DU_LOG("\nERROR --> RLC_DL : Memory Allocation failed UEID:%d CELLID:%d",\
414 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
418 boStatus->cellId = rbCb->rlcId.cellId;
419 boStatus->ueIdx = rbCb->rlcId.ueId;
420 boStatus->commCh = TRUE;
421 boStatus->lcId = rbCb->lch.lChId;
424 /* If trace flag is enabled send the trace indication */
425 if(gCb->init.trc == TRUE)
427 /* Populate the trace params */
428 rlcLmmSendTrc(gCb, EVENT_BO_STATUS_TO_MAC, NULLP);
431 /* Fill Pst structure. Copying rguSap->pst to pst to avoid any
432 * changes in rguSap->pst */
433 memset(&pst, 0, sizeof(Pst));
434 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
436 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
438 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
448 /********************************************************************30**
450 **********************************************************************/