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 Utility Module
26 This file contains following functions
31 --rlcUtlSendDedLcBoStatus
32 --rlcUtlSendUlDataToDu
37 **********************************************************************/
39 /** @file rlc_utl_dl.c
40 @brief RLC Utility Module
43 /* header (.h) include files */
45 #include "common_def.h"
46 /* kw005.201 added support for L2 Measurement */
50 #include "ckw.h" /* CKW defines */
51 #include "kwu.h" /* CKW defines */
52 #include "lkw.h" /* LKW defines */
53 #include "rgu.h" /* RGU defiens */
55 #include "rlc_env.h" /* RLC environment options */
56 #include "rlc_err.h" /* Error defines */
59 /* extern (.x) include files */
60 #include "ckw.x" /* CKW includes */
61 #include "kwu.x" /* KWU includes */
62 #include "lkw.x" /* LKW inlcudes */
63 #include "rgu.x" /* RGU includes */
65 #include "rlc_utils.h" /* RLC defines */
66 #include "rlc_dl_ul_inf.h"
67 #include "rlc_dl.h" /* RLC downlink includes */
68 #include "rlc_mac_inf.h"
69 #include "du_app_rlc_inf.h"
70 #include "rlc_lwr_inf_api.h"
71 #include "rlc_upr_inf_api.h"
78 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS))
79 uint32_t isDatReqProcessed;
81 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_DL) /* for debugging purpose */
82 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)) || defined (SS_RBUF)
83 void rlcUtlDlBatchProcHqStaInd ARGS ((Void));
85 Void ResetRLCStats(Void)
87 RlcCb* dlInst = rlcCb[1];
88 RlcCb* ulInst = rlcCb[0];
89 memset(&gRlcStats, 0, sizeof(RLCStats));
90 memset(&dlInst->genSts,0,sizeof(RlcGenSts));
91 memset(&ulInst->genSts,0,sizeof(RlcGenSts));
95 Void PrintRLCStats(Void)
97 RlcCb* dlInst = rlcCb[1];
98 RlcCb* ulInst = rlcCb[0];
100 DU_LOG("\nINFO --> RLC_DL : RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)",
101 dlInst->genSts.pdusSent,
102 dlInst->genSts.pdusRetx,
103 dlInst->genSts.protTimeOut,
104 dlInst->genSts.numSduDisc);
105 DU_LOG("\nINFO --> RLC_DL : RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)",
106 ulInst->genSts.pdusRecv,
107 ulInst->genSts.unexpPdusRecv,
108 ulInst->genSts.errorPdusRecv);
109 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMDL: "
110 "StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu ",
111 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu,
112 gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
113 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMDL: "
114 "DRB:%lu MaxRetx:%lu RetransPdus:%lu",
115 gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
116 gRlcStats.amRlcStats.numDLRetransPdus);
117 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMUL: "
118 " PdusDiscarded:%lu ReAsmblTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu ",
119 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReAsmblTimerExpires,
120 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
122 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)\n",
123 dlInst->genSts.pdusSent,
124 dlInst->genSts.pdusRetx,
125 dlInst->genSts.protTimeOut,
126 dlInst->genSts.numSduDisc);
127 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)\n",
128 ulInst->genSts.pdusRecv,
129 ulInst->genSts.unexpPdusRecv,
130 ulInst->genSts.errorPdusRecv);
131 RTLIN_DUMP_DEBUG("RLC Stats:"
132 "RLC_AMDL: StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu DRB:%lu MaxRetx:%lu RetransPdus:%lu \n"
133 "RLC_AMUL: PdusDiscarded:%lu ReAsmblTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu \n",
134 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused,
135 gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
136 gRlcStats.amRlcStats.numDLRetransPdus, gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReAsmblTimerExpires,
137 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
140 Void PrintRLCStats(Void)
142 RlcCb* dlInst = rlcCb[1];
143 RlcCb* ulInst = rlcCb[0];
145 DU_LOG ("\n ================================ RLC STATS ===========================\n");
146 DU_LOG("\nINFO --> RLC_DL : RLC Stats: PDUs Sent = (%d), PdusRext = (%d), TimeOut = (%d), SduDiscarded = (%d)",
147 dlInst->genSts.pdusSent,
148 dlInst->genSts.pdusRetx,
149 dlInst->genSts.protTimeOut,
150 dlInst->genSts.numSduDisc);
151 DU_LOG("\nINFO --> RLC_DL : RLC Stats: PDUs Rcvd = (%d), unexpPdus = (%d), errorPdus = (%d)",
152 ulInst->genSts.pdusRecv,
153 ulInst->genSts.unexpPdusRecv,
154 ulInst->genSts.errorPdusRecv);
155 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMDL: "
156 "StaPduSent:%u NacksInStaPdu:%u BytesUnused:%u PollTimerExpires SRB:%u ",
157 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu,
158 gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
159 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMDL: "
160 "DRB:%u MaxRetx:%u RetransPdus:%u",
161 gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
162 gRlcStats.amRlcStats.numDLRetransPdus);
163 DU_LOG("\nINFO --> RLC_DL : RLC Stats: AMUL: "
164 " PdusDiscarded:%u ReAsmblTimerExpires:%u StaPduRcvd:%u NackInStaPduRcvd:%u ",
165 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReAsmblTimerExpires,
166 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
167 /* RTLIN_DUMP_DEBUG("AM RLC Stats:"
168 "RLC_AMDL: SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) MaxRetx:(%u) WindowStalls: (%u) \n"
169 "RLC_AMUL: DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx :(%u) \n",
170 gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
171 gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmMaxRetx, gRlcStats.amRlcStats.numRlcAmCellWinStall,
172 gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
173 gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
175 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%d), PdusRext = (%d), TimeOut = (%d), SduDiscarded = (%d)\n",
176 dlInst->genSts.pdusSent,
177 dlInst->genSts.pdusRetx,
178 dlInst->genSts.protTimeOut,
179 dlInst->genSts.numSduDisc);
180 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%d), unexpPdus = (%d), errorPdus = (%d)\n",
181 ulInst->genSts.pdusRecv,
182 ulInst->genSts.unexpPdusRecv,
183 ulInst->genSts.errorPdusRecv);
184 RTLIN_DUMP_DEBUG("RLC_AMDL: StaPduSent:%u NacksInStaPdu:%u BytesUnused:%u PollTimerExpires SRB:%u DRB:%u MaxRetx:%u RetransPdus:%u \n"
185 " SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) WindowStalls: (%u) \n"
187 "RLC_AMUL: PdusDiscarded:%u ReAsmblTimerExpires:%u StaPduRcvd:%u NackInStaPduRcvd:%u \n"
188 " DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx:(%u) \n",
189 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused,
190 gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb,
191 gRlcStats.amRlcStats.numDLMaxRetx, gRlcStats.amRlcStats.numDLRetransPdus,
192 gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
193 gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmCellWinStall,
194 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReAsmblTimerExpires,
195 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd,
196 gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
197 gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
201 /*******************************************************************
204 * Handler for storing all DL PDU Info into RLC-MAC interface
205 * struct and sending to lower interface
208 * This function stores DL PDU info for all logical channels
209 * of per UE grant per TTI and sends to MAC
211 * Function : rlcSendDedLcDlData
214 * @return ROK - success
217 * ****************************************************************/
218 uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
220 uint8_t ueIdx; /* UE info list iterator */
221 uint8_t tbIdx; /* TB info list iterator */
222 uint8_t lchIdx; /* Lch info list iterator */
223 uint8_t pduIdx; /* RLC PDU list iterator */
224 RguDDatReqPerUe datPerUe; /* DL data info per UE */
225 RguDatReqTb datPerTb; /* DL data info per TB */
226 RguLchDatReq datPerLch; /* DL data info per Lch */
227 RlcData *dlData = NULLP; /* DL data to be sent to MAC */
228 RlcDlRrcMsgRsp *dlRrcMsgRsp = NULLP; /*DL RRC Rsp to be sent to DU*/
229 Pst pst; /* Post structure */
230 uint16_t pduLen; /* PDU length */
231 uint16_t copyLen; /* Number of bytes copied */
233 RlcBoStatus *boStatus = NULLP; /* Buffer occupancy status information */
236 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
237 dlData, sizeof(RlcData));
240 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed for dl data");
241 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
242 datReqInfo, sizeof(RguDDatReqInfo));
245 memset(dlData, 0, sizeof(RlcData));
247 for(ueIdx = 0; ueIdx < datReqInfo->nmbOfUeGrantPerTti; ueIdx++)
249 datPerUe = datReqInfo->datReq[ueIdx];
251 dlData->cellId = datReqInfo->cellId;
252 dlData->rnti = datPerUe.rnti;
253 /* Retrieving sfn/slot from transId. It was filled in RlcProcSchedResultRpt */
254 dlData->slotInfo.sfn = datPerUe.transId >> 16;
255 dlData->slotInfo.slot = datPerUe.transId & 0xffff;
259 for(tbIdx = 0; tbIdx < datPerUe.nmbOfTbs; tbIdx++)
261 datPerTb = datPerUe.datReqTb[tbIdx];
262 for(lchIdx = 0; lchIdx < datPerTb.nmbLch; lchIdx++)
264 datPerLch = datPerTb.lchData[lchIdx];
265 lcId = datPerLch.lcId;
266 for(pduIdx = 0; pduIdx < datPerLch.pdu.numPdu; pduIdx++)
268 dlData->pduInfo[dlData->numPdu].commCh = FALSE;
269 dlData->pduInfo[dlData->numPdu].lcId = datPerLch.lcId;
271 /* Copy Message to fixed buffer to send */
272 ODU_GET_MSG_LEN(datPerLch.pdu.mBuf[pduIdx], (MsgLen *)&pduLen);
273 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
274 dlData->pduInfo[dlData->numPdu].pduBuf, pduLen);
276 if (dlData->pduInfo[dlData->numPdu].pduBuf == NULLP )
278 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed");
279 for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
281 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlData->pduInfo[pduIdx].pduBuf,\
282 dlData->pduInfo[pduIdx].pduLen);
284 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
285 dlData, sizeof(RlcData));
286 RLC_FREE_SHRABL_BUF(post->region, post->pool,
287 datReqInfo, sizeof(RguDDatReqInfo));
291 ODU_COPY_MSG_TO_FIX_BUF(datPerLch.pdu.mBuf[pduIdx], 0, pduLen, \
292 dlData->pduInfo[dlData->numPdu].pduBuf, (MsgLen *)©Len);
293 dlData->pduInfo[dlData->numPdu].pduLen = pduLen;
296 ODU_PUT_MSG_BUF(datPerLch.pdu.mBuf[pduIdx]);
300 dlData->boStatus[dlData->numLc].cellId = datReqInfo->cellId;
301 GET_UE_ID(datPerUe.rnti, dlData->boStatus[dlData->numLc].ueId);
302 dlData->boStatus[dlData->numLc].commCh = false;
303 dlData->boStatus[dlData->numLc].lcId = datPerLch.lcId;
304 dlData->boStatus[dlData->numLc].bo = datPerLch.boReport.bo + datPerLch.boReport.estRlcHdrSz;
306 }/* For Data per Lch */
307 }/* For Data per Tb */
309 /*No Data to send for this UE, Only send the BO REQUEST to SCH */
310 if(dlData->numPdu == 0)
312 for(lchIdx = 0; lchIdx < dlData->numLc; lchIdx++)
314 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, \
315 boStatus, sizeof(RlcBoStatus));
316 if(boStatus == NULLP)
318 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed for boStatus");
322 boStatus->cellId = dlData->cellId;
323 GET_UE_ID(dlData->rnti, boStatus->ueId);
324 boStatus->commCh = FALSE;
325 boStatus->lcId = dlData->boStatus[lchIdx].lcId;
326 boStatus->bo = dlData->boStatus[lchIdx].bo;
328 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_BO_STATUS_TO_MAC);
329 /* Send Status Response to MAC layer */
330 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
332 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Failed to send BO status");
333 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
337 DU_LOG("\nDEBUG --> RLC_DL : rlcSendDedLcDlData: BO Status sent successfully for LCID:%d,BO:%d",\
338 boStatus->lcId, boStatus->bo);
340 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlData, sizeof(RlcData));
341 RLC_FREE_SHRABL_BUF(post->region, post->pool, datReqInfo, sizeof(RguDDatReqInfo));
345 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
346 if(dlRrcMsgRsp == NULLP)
348 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Memory allocation failed for dlRrcMsgRsp");
349 for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
351 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
352 dlData->pduInfo[pduIdx].pduLen);
354 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
355 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
356 datReqInfo, sizeof(RguDDatReqInfo));
359 dlRrcMsgRsp->cellId = dlData->cellId;
360 dlRrcMsgRsp->crnti = dlData->rnti;
362 /* Sending DL Data per UE to MAC */
363 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
364 if(RlcSendDlDataToMac(&pst, dlData) != ROK)
366 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Failed to send Dl RRC Msg To Mac");
367 dlRrcMsgRsp->state = TRANSMISSION_FAILED;
368 for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
370 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
371 dlData->pduInfo[pduIdx].pduLen);
373 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
374 RLC_FREE_SHRABL_BUF(post->region, post->pool, datReqInfo, sizeof(RguDDatReqInfo));
375 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
379 dlRrcMsgRsp->state = TRANSMISSION_COMPLETE;
381 FILL_PST_RLC_TO_DUAPP(pst, RLC_DL_INST, EVENT_DL_RRC_MSG_RSP_TO_DU);
382 if(lcId >= SRB1_LCID && lcId <= SRB3_LCID) /* Valid for all RRC messages i.e. SRB1, SRB2, SRB3 */
384 if(rlcSendDlRrcMsgRspToDu(&pst, dlRrcMsgRsp) != ROK)
386 DU_LOG("\nERROR --> RLC_DL : rlcSendDedLcDlData: Failed to send Dl RRC Msg Rsp To Du");
387 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
388 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo, sizeof(RguDDatReqInfo));
394 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
397 } /* For Data per UE */
398 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo, sizeof(RguDDatReqInfo));
401 }/* End of rlcSendDedLcDlData */
406 * Handler for sending the data to multiple logical channels of a UE
409 * This function sends the data for one or more logical channels
410 * after processing the SDUs and forming the PDUs.It calls
411 * UMM or AMM functions to form the PDUs for the requested sizes
414 * @param[in] gCb RLC instance Control block
415 * @param[in] staIndInfo Status Indication Information containing the
416 * size of PDU(s) for one or more logical channels
423 uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
427 RlcDlUeCb *ueCb; /* UE control block */
428 uint32_t count; /* Loop Counter */
429 uint32_t numTb; /* Number of Tbs */
430 RlcDlRbCb *rbCb; /* RB Control Block */
431 RlcDatReq datReq; /* PDUs Information */
432 RguDDatReqInfo *datReqInfo; /* Data Request Information */
433 RlcRguSapCb *rguSap; /* MAC SAP CB */
434 uint32_t totNumPdu; /* Total number of PDUS */
436 RguStaIndTb *staIndTb = NULLP;
437 RguDatReqTb *datReqTb = NULLP;
438 RguDStaIndPerUe *staInd = NULLP;
440 uint32_t grantPerLch[RGU_MAX_LC] = {0};
442 /* kw005.201 added support for L2 Measurement */
443 #ifdef LTE_L2_MEAS_LOSS_DELAY
446 #endif /* LTE_L2_MEAS */
447 uint32_t idx, ueDataIdx = 0;
450 uint32_t staIndSz=0,datIndSz = 0;
451 RlcTptPerSnssai *snssaiTputNode = NULLP;
454 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
455 datReqInfo,sizeof(RguDDatReqInfo));
456 #if (ERRCLASS & ERRCLS_ADD_RES)
457 if ( datReqInfo == NULLP )
459 DU_LOG("\nERROR --> RLC_DL : rlcUtlSendToMac: Memory allocation failed");
462 #endif /* ERRCLASS & ERRCLS_ADD_RES */
463 for(idx = 0; idx < staIndInfo->nmbOfUeGrantPerTti; idx++)
465 staInd = &staIndInfo->staInd[idx];
466 /* Fetch Ue control block */
467 GET_UE_ID(staInd->rnti, ueId);
468 if(ROK != rlcDbmFetchDlUeCb(gCb, ueId, staIndInfo->cellId, &ueCb))
470 /* Fetch UeCb failed */
471 DU_LOG("\nERROR --> RLC_DL : rlcUtlSendToMac: UeId[%u]:ueCb not found",
473 /* If ueCb is not found for current rnti then continue to look for next rnti*/
477 /* kw002.201 Removed the allocation of RlcDatReq */
478 /* kw004.201 Used SSI function to initialize the variable */
479 memset(&datReq, 0, sizeof(RlcDatReq) );
481 for (numTb = 0; numTb < staInd->nmbOfTbs; numTb++)
483 staIndTb = &(staInd->staIndTb[numTb]);
484 datReqTb = &(datReqInfo->datReq[ueDataIdx].datReqTb[numTb]);
486 ueCb->tbIdx = (ueCb->tbIdx+1) % RLC_MAX_TB_PER_UE;
488 snssaiTputNode = NULLP;
489 for (count = 0;count < staIndTb->nmbLch; count++)
492 /*Calculate the total grant size from MAC */
493 if((staIndTb->lchStaInd[count].lcId >= RGU_MAX_LC)
494 || (staIndTb->lchStaInd[count].lcId == 0))
496 /* TODO : Need to figure out why this is happening */
501 grantPerLch[staIndTb->lchStaInd[count].lcId] += staIndTb->lchStaInd[count].totBufSize;
504 rbCb = ueCb->lCh[staIndTb->lchStaInd[count].lcId - 1].dlRbCb;
506 if (rbCb && (!rlcDlUtlIsReestInProgress(rbCb)))
508 /* Cosider buffer size for throughput calculation */
509 if(gCb->rlcThpt.ueTputInfo.thptPerUe[ueId-1].ueId == ueId)
510 gCb->rlcThpt.ueTputInfo.thptPerUe[ueId-1].dataVol += staIndTb->lchStaInd[count].totBufSize;
514 snssaiTputNode = rlcHandleSnssaiTputlist(gCb, rbCb->snssai, SEARCH, DIR_DL);
515 if(snssaiTputNode != NULLP)
517 snssaiTputNode->dataVol += staIndTb->lchStaInd[count].totBufSize;
518 DU_LOG("\nINFO -->SCH: SNSSAI List Grant:%d, lcId:%d, total :%ld",\
519 staIndTb->lchStaInd[count].totBufSize, staIndTb->lchStaInd[count].lcId,\
520 snssaiTputNode->dataVol);
524 staIndSz += staIndTb->lchStaInd[count].totBufSize;
525 datReq.pduSz = staIndTb->lchStaInd[count].totBufSize;
527 datReq.totMacGrant = grantPerLch[staIndTb->lchStaInd[count].lcId];
529 rlcUtlGetCurrTime(&datReq.boRep.oldestSduArrTime);
530 if ( RLC_MODE_UM == rbCb->mode )
532 rlcUmmProcessSdus(gCb,rbCb,&datReq);
534 else if ( RLC_MODE_AM == rbCb->mode )
536 rlcAmmProcessSdus(gCb,rbCb,&datReq,staInd->fillCtrlPdu);
539 grantPerLch[staIndTb->lchStaInd[count].lcId] = datReq.totMacGrant;
541 datReqTb->lchData[count].setMaxUlPrio = FALSE;
542 if (RLC_AM_IS_POLL_BIT_SET(RLC_AMDL) &&
543 (RLC_AMDL.sduQ.count > 1))
545 /* Poll bit is set indicate to MAC*/
546 datReqTb->lchData[count].setMaxUlPrio = TRUE;
548 datReqTb->lchData[count].boReport.bo = datReq.boRep.bo;
551 datReqTb->lchData[count].boReport.estRlcHdrSz =
552 datReq.boRep.estHdrSz;
553 datReqTb->lchData[count].boReport.staPduPrsnt =
554 datReq.boRep.staPduPrsnt;
555 #endif /* CCPU_OPT */
556 datReqTb->lchData[count].boReport.staPduBo =
557 datReq.boRep.staPduBo;
558 datReqTb->lchData[count].lcId = staIndTb->lchStaInd[count].lcId;
561 /* Set if Bearer is UM */
562 if ( RLC_MODE_UM == rbCb->mode )
564 datReqTb->lchData[count].freeBuff = TRUE;
568 datReqTb->lchData[count].freeBuff = FALSE;
572 datReqTb->lchData[count].boReport.oldestSduArrTime =
573 datReq.boRep.oldestSduArrTime;
574 if ( 0 == datReq.pduInfo.numPdu )
576 /* kw004.201 Used SSI function to initialize the variable */
577 memset(&datReq, 0, sizeof(RlcDatReq) );
580 totNumPdu += datReq.pduInfo.numPdu;
581 memcpy(&(datReqTb->lchData[count].pdu),
582 &(datReq.pduInfo),sizeof(KwPduInfo));
584 for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
586 ODU_GET_MSG_LEN(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
589 /* kw005.201 added support for L2 Measurement */
590 #ifdef LTE_L2_MEAS_LOSS_DELAY
591 datReqTb->rguSnInfo->lchMap[count].lChId =
592 staIndTb->lchStaInd[count].lcId;
593 /* In some cases L2 Measurement for few of the lcId may be off,
594 * in this case we are assigning snList to 0xffff
596 for(snIdx1 = 0; snIdx1 < RGU_MAX_PDU; snIdx1++)
598 datReqTb->rguSnInfo->lchMap[count].snList[snIdx1] = 0xffff;
600 if(tbSnMap->numSn != 0)
603 for(snIdx1=tbSnMap->prevNumSn;snIdx1 < tbSnMap->numSn;snIdx1++)
605 datReqTb->rguSnInfo->lchMap[count].snList[snIdx2++] =
606 tbSnMap->snSduMap[snIdx1].sn;
608 tbSnMap->prevNumSn = tbSnMap->numSn;
611 /* kw004.201 Used SSI function to initialize the variable */
612 memset(&datReq, 0, sizeof(RlcDatReq) );
616 if(ueCb->l2MeasTbCb[ueCb->tbIdx]!= NULLP)
618 datReqTb->tbId = ueCb->tbIdx;
622 datReqTb->tbId = RLC_INVALID_TBID;
625 datReqTb->nmbLch = staIndTb->nmbLch;
627 /* kw005.201 added support for L2 Measurement */
628 #ifdef LTE_L2_MEAS_LOSS_DELAY
629 if(tbSnMap->numSn == 0)
631 RLC_FREE(tbSnMap,sizeof(RlcTbSnMap));
632 RLC_FREE(datReqTb->rguSnInfo,sizeof(RguSnMapInfo));
633 datReqTb->rguSnInfo = NULLP;
634 rlcCb.rlcL2Cb.curTbSnMap = NULLP;
635 datReqTb->snMapPres = FALSE;
639 cmHashListInsert(&(rlcCb.rlcL2Cb.tbHlCp),(PTR)tbSnMap,
640 (uint8_t *) &(tbSnMap->tbId), (uint16_t)sizeof(tbSnMap->tbId));
641 rlcCb.rlcL2Cb.curTbSnMap = NULLP;
643 #endif /* LTE_L2_MEAS */
645 datReqInfo->datReq[ueDataIdx].nmbOfTbs = staInd->nmbOfTbs;
646 datReqInfo->datReq[ueDataIdx].transId = staInd->transId;
647 datReqInfo->datReq[ueDataIdx].rnti = staInd->rnti;
653 datReqInfo->cellId = staIndInfo->cellId;
654 datReqInfo->nmbOfUeGrantPerTti = staIndInfo->nmbOfUeGrantPerTti;
656 rguSap = &(gCb->u.dlCb->rguDlSap[suId]);
657 rlcSendDedLcDlData(&rguSap->pst,rguSap->spId,datReqInfo);
661 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, datReqInfo,sizeof(RguDDatReqInfo));
669 * Handler for sending Status Response to MAC.
672 * This function is used by RLC entity for sending
673 * status response to MAC after receiving a SDU from
676 * @param[in] gCb RLC instance Control block
677 * @param[in] rbCb Radio Bearer Control Block
678 * @param[in] bo Buffer Occupancy
679 * @param[in] estHdrSz Estimated Header Size
680 * @param[in] staPduPrsnt Status PDU present or not
686 uint8_t rlcUtlSendDedLcBoStatus(RlcCb *gCb, RlcDlRbCb *rbCb, int32_t bo, \
687 int32_t estHdrSz, bool staPduPrsnt, uint32_t staPduBo)
689 Pst pst; /* Post info */
690 RlcBoStatus *boStatus; /* Buffer occupancy status information */
693 if ((rbCb->lastRprtdBoToMac > (uint32_t)8000) && (rbCb->boUnRprtdCnt < (uint32_t)5)
694 && (!staPduPrsnt) && ((RLC_MODE_AM == rbCb->mode ) && (RLC_AMDL.nxtRetx == NULLP)))
696 rbCb->boUnRprtdCnt++;
700 rbCb->boUnRprtdCnt = (uint32_t)0;
701 rbCb->lastRprtdBoToMac = (uint32_t)bo;
703 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, \
704 boStatus, sizeof(RlcBoStatus));
706 boStatus->cellId = rbCb->rlcId.cellId;
707 boStatus->ueId = rbCb->rlcId.ueId;
708 boStatus->commCh = FALSE;
709 boStatus->lcId = rbCb->lch.lChId;
710 boStatus->bo = bo + estHdrSz;
712 FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_BO_STATUS_TO_MAC);
713 /* Send Status Response to MAC layer */
714 if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
716 RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
725 * Handler for emptying the SDU queue.
728 * This function is used to empty the SDU queue when
729 * a re-establishment request is received from the
732 * @param[in] gCb RLC instance control block
733 * @param[in] rbCb Radio bearer control block
734 * @param[in] sduQ SDU queue to be emptied
738 /* kw005.201 added support for L2 Measurement */
739 #ifdef LTE_L2_MEAS_RLC
754 #ifdef LTE_L2_MEAS_RLC
755 CmLListCp *sduSnMapQ; /* SDU Sequence number map queue */
756 CmLList *firstSduSnMap; /* First Node in SDU SnMap Queue */
757 RlcSduSnMap *sduSnMap; /* SDU Sn Map */
760 firstSduSnMap = NULLP;
764 sduSnMapQ = &rbCb->sduSnMapQ;
765 CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
769 sduSnMap = (RlcSduSnMap *)firstSduSnMap->node;
770 if(sduSnMap != NULLP)
772 cmLListDelFrm(&(rbCb->sduSnMapQ), &(sduSnMap->lstEnt));
773 RLC_FREE(sduSnMap, sizeof(RlcSduSnMap));
774 CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
778 CM_LLIST_NEXT_NODE(sduSnMapQ, firstSduSnMap);
788 * Function to set that re-establishment has started for an RB
791 * This function is used to set the reestInProgress flag to TRUE.
792 * This also sets the estimated header size to 0 and sends bo as
793 * 0 to MAC so that RLC does not need to transmit any data.
794 * If the poll re-transmit timer is running for the RB;
797 * @param[in] gCb RLC instance control block
798 * @param[in] rbCb RB for which re-establishment has started
802 Void rlcDlUtlSetReestInProgressForRB(RlcCb *gCb,RlcDlRbCb *rbCb)
805 rbCb->reestInProgress = TRUE;
807 if(rbCb->mode == RLC_MODE_AM )
809 rbCb->m.amDl.estHdrSz = 0;
811 if(rlcChkTmr(gCb, (PTR)rbCb, EVENT_RLC_AMDL_POLL_RETX_TMR))
813 rlcStopTmr(gCb, (PTR)rbCb, EVENT_RLC_AMDL_POLL_RETX_TMR);
816 rlcUtlSendDedLcBoStatus(gCb, rbCb, 0, 0, FALSE,0);
824 * Function to check if re-establishment is ongoing for an RB
826 * @param[in] rbCb RB for which re-establishment is to be checked
829 * TRUE : Re-establishment is in progress
830 * FALSE : Re-establishment is not in progress
832 bool rlcDlUtlIsReestInProgress(RlcDlRbCb *rbCb)
834 return (rbCb->reestInProgress);
840 * Function to set re-establishment to FALSE
842 * @param[in] rbCb RB for which re-establishment is to be reset
846 Void rlcDlUtlResetReestInProgress(RlcDlRbCb *rbCb)
849 rbCb->reestInProgress = FALSE;
855 * Function to set that re-establishment has started for all the RBs
856 * of an UE; except for SRB1
858 * @detail: For SRB1 only the poll-retransmit timer is stopped
860 * @param[in] gCb RLC instance control block
861 * @param[in] ueCb UE for which re-establishment has started
865 Void rlcDlUtlSetReestInProgressForAllRBs(RlcCb *gCb,RlcDlUeCb *ueCb)
869 for(rbIdx = 0;rbIdx < RLC_MAX_SRB_PER_UE;rbIdx++)
871 if(ueCb->srbCb[rbIdx] != NULLP)
873 if(ueCb->srbCb[rbIdx]->rlcId.rbId != 1)
875 rlcDlUtlSetReestInProgressForRB(gCb,ueCb->srbCb[rbIdx]);
879 /* For SRB we just need to stop the poll re-transmit timer */
880 if(rlcChkTmr(gCb, (PTR)ueCb->srbCb[rbIdx], EVENT_RLC_AMDL_POLL_RETX_TMR))
882 rlcStopTmr(gCb, (PTR)ueCb->srbCb[rbIdx], EVENT_RLC_AMDL_POLL_RETX_TMR);
888 for(rbIdx = 0;rbIdx < RLC_MAX_DRB_PER_UE;rbIdx++)
890 if(ueCb->drbCb[rbIdx] != NULLP)
892 rlcDlUtlSetReestInProgressForRB(gCb,ueCb->drbCb[rbIdx]);
900 * @brief Function to increment number of SDUs transmitted
901 * in KWU SAP statistics
904 * @param[in] rlckwuSap KWU SAP in which to increment the counter
908 void rlcUtlIncrementKwuStsSduTx(RlcKwuSapCb *rlckwuSap)
910 rlckwuSap->sts.sduTx++;
915 * @brief Function to increment number of bytes and PDUs transmitted
916 * in General statistics
919 * @param[in] genSts KWU SAP in which to increment the counter
920 * @param[in] pdu The PDU which is sent
924 void rlcUtlIncrementGenStsBytesAndPdusSent(RlcGenSts *genSts, Buffer *pdu)
927 ODU_GET_MSG_LEN(pdu, &bytesSent);
928 genSts->bytesSent += bytesSent;
934 * @brief Function to initialize the data structures used to free memory
937 * @param[in] gCb RLC instance control block
938 * @param[out] toBeFreed Pointer to the freeing structure. This is
943 Void rlcUtlInitToBeFreed(RlcCb *gCb,RlcDlDataToBeFreed *toBeFreed)
945 cmLListInit(&(toBeFreed->sduLst));
946 cmLListInit(&(toBeFreed->rbLst));
947 cmLListInit(&(toBeFreed->reTxLst));
948 cmLListInit(&(toBeFreed->txLst));
954 * @brief Function to initialize the DL self Pst structure
957 * @param[in] gCb RLC instance control block
961 Void rlcUtlInitializeSelfPst(RlcCb *gCb)
963 Pst *selfPst = &gCb->u.dlCb->selfPst;
965 RLC_MEM_SET(selfPst, 0, sizeof(Pst));
966 selfPst->srcProcId = SFndProcId();
967 selfPst->dstProcId = SFndProcId();
968 selfPst->dstEnt = gCb->init.ent;
969 selfPst->dstInst = gCb->init.inst; /* this is for the DL instance */
970 selfPst->srcEnt = gCb->init.ent;
971 selfPst->srcInst = gCb->init.inst; /* DL instance will send to itself */
972 selfPst->prior = PRIOR3;
973 selfPst->event = UDX_EVT_DL_CLEANUP_MEM;
977 * @brief Function to send a DL cleanup event
980 * @param[in] gCb RLC instance control block
984 void rlcUtlRaiseDlCleanupEvent(RlcCb *gCb)
986 #ifdef KWSELFPSTDLCLEAN
987 if(!gCb->u.dlCb->eventInQueue)
989 ODU_POST_TASK(&gCb->u.dlCb->selfPst, gCb->u.dlCb->selfPstMBuf);
990 gCb->u.dlCb->eventInQueue = TRUE;
997 * @brief Function to add a SDU to the to be freed sdu list
1000 * @param[in] gCb RLC instance control block
1001 * @param[in] sdu SDU to be added to the list
1005 void rlcUtlAddSduToBeFreedQueue(RlcCb *gCb, RlcSdu *sdu)
1007 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.sduLst), &(sdu->lstEnt));
1012 * @brief Function to add a re-transmitted pdu to the to be freed list
1015 * @param[in] gCb RLC instance control block
1016 * @param[in] retx Re-transmitted pdu to be added to the list
1020 Void rlcUtlAddReTxPduToBeFreedQueue(RlcCb *gCb,RlcRetx *retx)
1022 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.reTxLst), &(retx->lstEnt));
1027 * @brief Function to add a transmitted pdu to the to be freed list
1030 * @param[in] gCb RLC instance control block
1031 * @param[in] pdu PDU to be added to the list
1035 Void rlcUtlAddTxPduToBeFreedQueue(RlcCb *gCb,RlcTx *pdu)
1037 pdu->rlsLnk.node = (PTR)pdu;
1038 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.txLst), &(pdu->rlsLnk));
1044 * function to free/release the Acknowledged mode RBCB buffers
1047 * This primitive Frees the Acknowledged Mode RbCb transmission Buffer,
1048 * retransmission Buffer and reciption Buffers
1050 * @param [in] gCb - RLC instance control block
1051 * @param [in] rbCb - Downlink RB Control Block
1052 * @param [in,out] toBeFreed - Number of buffers to be freed
1055 * - TRUE if more data to be freed
1056 * - FALSE if all the data has been freed
1058 static Bool rlcUtlFreeDlAmRbMemory(RlcCb *gCb,RlcDlRbCb *rbCb,uint32_t *toBeFreed)
1060 RlcRetx *retx; /* retransmission buffer */
1061 RlcSn mTxNext; /* send state variable */
1064 MODAMT(RLC_AMDL.txNext, mTxNext, RLC_AMDL.txNextAck,RLC_AMDL.snModMask);
1066 /* TODO : to be checked changed from <= to < */
1067 while ((0 < mTxNext) && *toBeFreed)
1069 txBuf = rlcUtlGetTxBuf(RLC_AMDL.txBufLst, RLC_AMDL.txNextAck);
1070 if (txBuf && txBuf->pduLst.first)
1072 while(txBuf->pduLst.first)
1074 RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(txBuf->pduLst.first->node);
1075 ODU_PUT_MSG_BUF(pduInfo->pdu);
1076 /* Delete node from the txBuf Pdu lst */
1077 cmLListDelFrm(&txBuf->pduLst, txBuf->pduLst.first);
1078 RLC_FREE(gCb, pduInfo, sizeof(RlcDlPduInfo));
1080 rlcUtlDelTxBuf(RLC_AMDL.txBufLst, txBuf, gCb);
1081 if(gCb->u.dlCb->shutdownReceived == 0)
1086 RLC_AMDL.txNextAck = (RLC_AMDL.txNextAck + 1) & RLC_AMDL.snModMask;
1087 MODAMT(RLC_AMDL.txNext, mTxNext, RLC_AMDL.txNextAck,RLC_AMDL.snModMask);
1089 RLC_FREE(gCb, rbCb->snssai, sizeof(Snssai));
1096 RLC_FREE(gCb,RLC_AMDL.txBufLst, (RLC_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
1099 RLC_LLIST_FIRST_RETX(RLC_AMDL.retxLst, retx);
1100 while (retx && (*toBeFreed)) /* Till to be freed becomes 0 */
1103 ODU_PUT_MSG_BUF(retx->seg);
1105 cmLListDelFrm(&RLC_AMDL.retxLst, &retx->lstEnt);
1106 RLC_FREE(gCb, retx, sizeof(RlcRetx));
1108 RLC_LLIST_FIRST_RETX(RLC_AMDL.retxLst, retx);
1109 if(gCb->u.dlCb->shutdownReceived == 0)
1116 RLC_AMDL.nxtRetx = NULLP;
1118 /* clean up if there is info about STATUS PDU to be sent */
1119 if(RLC_AMDL.pStaPdu)
1122 udxPst = &gCb->u.dlCb->udxDlSap->pst;
1123 RLC_FREE_SHRABL_BUF_WC(udxPst->region,
1126 sizeof(RlcUdxDlStaPdu));
1127 RLC_AMDL.pStaPdu = NULLP;
1134 if(gCb->u.dlCb->shutdownReceived)
1143 * @brief Function to free memory from the DL instance
1146 * @param[in] gCb RLC instance control block
1150 Void rlcUtlFreeDlMemory(RlcCb *gCb)
1154 /* safety check, in case some event was still lying in the queue after
1155 the dlCb was deleted*/
1161 RlcDlDataToBeFreed* pToBeFreed = &gCb->u.dlCb->toBeFreed;
1163 if(gCb->u.dlCb->shutdownReceived)
1165 toBeFreed = pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count + pToBeFreed->rbLst.count;
1169 if ((pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count) > (3 * RLC_MAX_TO_BE_FREED))
1171 #if !defined(KWSELFPSTDLCLEAN) && defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
1172 if (isDatReqProcessed)
1174 toBeFreed = (2 *RLC_MAX_TO_BE_FREED);
1179 toBeFreed = (3 *RLC_MAX_TO_BE_FREED)/2;
1184 toBeFreed = RLC_MAX_TO_BE_FREED;
1189 gCb->u.dlCb->eventInQueue = FALSE; /* reset as we have received the event
1190 and are processing it */
1192 /* Free from the ReTx list */
1193 lst = &pToBeFreed->reTxLst;
1194 while((lst->first) && toBeFreed)
1196 RlcRetx* seg = (RlcRetx *)(lst->first->node);
1197 cmLListDelFrm(lst, lst->first);
1198 ODU_PUT_MSG_BUF(seg->seg);
1199 RLC_FREE(gCb,seg, sizeof(RlcRetx));
1203 /* Free from the Tx list */
1204 lst = &pToBeFreed->txLst;
1205 while((lst->first) && toBeFreed)
1207 RlcTx* pdu = (RlcTx *)(lst->first->node);
1208 cmLListDelFrm(lst, lst->first);
1209 while(pdu->pduLst.first)
1211 RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(pdu->pduLst.first->node);
1213 cmLListDelFrm(&pdu->pduLst, pdu->pduLst.first);
1214 ODU_PUT_MSG_BUF(pduInfo->pdu);
1215 RLC_FREE(gCb, pduInfo, sizeof(RlcDlPduInfo));
1217 RLC_FREE(gCb,pdu, sizeof(RlcTx));
1221 /* Free from the SDU queue */
1222 lst = &pToBeFreed->sduLst;
1223 while((lst->first) && toBeFreed)
1225 RlcSdu* sdu = (RlcSdu *)(lst->first->node);
1226 RLC_REMOVE_SDU(gCb, lst, sdu);
1230 /* Free from the RBs */
1231 lst = &pToBeFreed->rbLst;
1232 while((lst->first) && toBeFreed)
1234 RlcDlRbCb* rbCb = (RlcDlRbCb *)(lst->first->node);
1235 Bool moreToBeFreed = rlcUtlFreeDlAmRbMemory(gCb, rbCb,&toBeFreed);
1238 cmLListDelFrm(lst, lst->first);
1239 RLC_FREE(gCb, rbCb, sizeof(RlcDlRbCb));
1243 if ((toBeFreed == 0) && !(gCb->u.dlCb->shutdownReceived))
1245 rlcUtlRaiseDlCleanupEvent(gCb);
1255 * @brief Function to initialise measurement
1259 * @param[in] gCb RLC Instance Control Block
1264 S16 rlcUtlL2MeasDlInit(RlcCb *gCb)
1268 gCb->u.dlCb->rlcL2Cb.rlcNumMeas=0;
1269 for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
1271 memset(&(gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
1273 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DISC].measCb.measType = LKW_L2MEAS_DL_DISC;
1274 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_IP].measCb.measType = LKW_L2MEAS_DL_IP;
1275 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DELAY].measCb.measType= LKW_L2MEAS_DL_DELAY;
1276 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UU_LOSS].measCb.measType= LKW_L2MEAS_UU_LOSS;
1277 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_ACT_UE].measCb.measType= LKW_L2MEAS_ACT_UE;
1283 * @brief Function to detect the data Burst start Condition in a DTCH
1287 * @param[in] rbCb RB control block
1288 * @param[in] contSduLst Array of Contained SDUs in the DTCH
1289 * @param[in] dataVol Available data in the DTCH
1290 * @param[in] schPduSz Total grant Size given by MAC
1295 Void rlcUtlUpdateBurstSdus
1299 RlcContSduLst *contSduLst,
1305 RlcL2MeasDlIpTh *l2MeasDlIpThruput = NULLP;
1306 RlcL2MeasTb *l2MeasTb = NULLP;
1309 volatile uint32_t startTime = 0;
1310 RlcContSduLst *dstContSduLst;
1314 SStartTask(&startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1316 l2MeasDlIpThruput = &rbCb->l2MeasIpThruput.dlIpTh;
1318 if(RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb, rbCb))
1320 if(dataVol > schPduSz)
1322 if(l2MeasDlIpThruput->isBurstAct == FALSE)
1324 l2MeasDlIpThruput->burstStartTime = glblTtiCnt;
1325 l2MeasDlIpThruput->isBurstAct = TRUE;
1326 l2MeasDlIpThruput->burstEndSduId = 0;
1329 { /* This is the case when another burst started before RLC gets the
1330 l2MeasDlIpThruput->burstEndSduId = 0; */
1334 { /* Store the burstEndSduId here */
1335 if((l2MeasDlIpThruput->isBurstAct == TRUE) &&
1336 (!l2MeasDlIpThruput->burstEndSduId))
1338 l2MeasDlIpThruput->burstEndSduId =
1339 l2MeasDlIpThruput->outStngSduArr[l2MeasDlIpThruput->lastSduIdx].sduId;
1342 if(l2MeasDlIpThruput->isBurstAct == TRUE)
1344 l2MeasTb = rlcUtlGetCurMeasTb(gCb,rbCb);
1345 /* Get the lChId from index 0, because index 0 is always for DL */
1346 if(l2MeasTb->numLcId >= RLC_MAX_ACTV_DRB)
1351 l2MeasTb->sduInfo[l2MeasTb->numLcId].lcId = rbCb->lch.lChId;
1352 /* Copy all the sduIdx from sduInfo to tb sduInfo */
1353 currTbIdx = l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus;
1354 dstContSduLst = &l2MeasTb->sduInfo[l2MeasTb->numLcId];
1356 for(idx = 0; ((idx < contSduLst->numSdus)
1357 && (currTbIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)) ; idx++)
1359 dstContSduLst->sduIdx[currTbIdx++] = contSduLst->sduIdx[idx];
1361 l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus += idx;
1362 l2MeasTb->numLcId++;
1363 }/* End of isBurstAct */
1364 }/* End of if measOn */
1367 SStopTask(startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1372 * This function is used to store locally the sduIdx of the sdu in the
1373 * outstanding SDU array
1376 * Stores the Sdu Idx in the contained SDU Array and increments
1377 * the num contained Sdus
1379 * @param[in] sduIdx the Index of the SDU in the outstanding SDU array
1380 * @param[out] contSduLst This stores the indices of the SDUs
1384 Void rlcUtlUpdateContainedSduLst(uint8_t sduIdx,RlcContSduLst *contSduLst)
1386 if (contSduLst->numSdus < RLC_L2MEAS_MAX_OUTSTNGSDU)
1388 contSduLst->sduIdx[contSduLst->numSdus] = sduIdx;
1389 contSduLst->numSdus++;
1396 * This function is used to store the sduId of the sdu in the
1397 * outstanding SDU array
1400 * Stores the Sdu Id in the outstanding SDU Array and increments
1401 * the num contained Sdus
1403 * @param[out] dlIpThPut The structure in which the outstanding sdus are
1405 * @param[in] sduIdx The Idx at which the sdu ID is stored
1406 * @param[in] sduLen The size if sdu in bytes
1407 * @param[in] newIdx Indicates if the sdu is already present in the
1412 Void rlcUtlUpdateOutStandingSduLst
1414 RlcL2MeasDlIpTh *dlIpThPut,
1421 if (sduIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)
1425 dlIpThPut->outStngSduArr[sduIdx].numTb = 0;
1427 dlIpThPut->outStngSduArr[sduIdx].numTb++;
1428 dlIpThPut->outStngSduArr[sduIdx].sduId = sduId;
1429 dlIpThPut->outStngSduArr[sduIdx].sduLen = sduLen;
1433 RlcL2MeasTb * rlcUtlGetCurMeasTb(RlcCb *gCb,RlcDlRbCb *rbCb)
1435 RlcL2MeasTb *curL2MeasTb;
1438 if((curL2MeasTb = rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx]) == NULLP)
1440 /* Intentionally avoiding the RLC_ALLOC macro to avoid memset */
1441 RLC_ALLOC(gCb, curL2MeasTb, (Size)sizeof(RlcL2MeasTb));
1442 if(curL2MeasTb == NULLP)
1444 DU_LOG("ERROR --> RLC_DL : rlcUtlGetCurMeasTb(): Memory allocation failed");
1447 rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx] = curL2MeasTb;
1448 /* Initialize the Meas Tb details */
1449 curL2MeasTb->numLcId = 0;
1450 curL2MeasTb->numLchInfo = 0;
1451 curL2MeasTb->txSegSduCnt = 0;
1452 for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1454 curL2MeasTb->sduInfo[idx].numSdus = 0;
1456 for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1458 curL2MeasTb->lchInfo[idx].numSdus = 0;
1461 return (curL2MeasTb);
1467 * @brief Handler for Processing harq status indication
1471 * This function is called when the MAC sends a harq ind Mesage.
1472 * This is used only for UuLoss and Dl Delay and DL Ipthoughput
1475 * @param[in] staInd Harq status indication received from MAC.
1476 * @param[in] ueCb UeCb corresponding to the Tb Id.
1477 * @param[in] tbIdx TB index, 0 for SISO and 0,1 for MIMO.
1484 S16 rlcUtlProcHarqInd
1487 RguHarqStatusInd *hqStaInd,
1493 RlcDlRbCb *rlcRbCb; /* KW Control Block */
1494 RlcL2MeasTb *l2MeasTb = NULLP; /* Measurement TbCb */
1495 uint8_t lcIdx; /* Logical channel id index */
1496 uint8_t sduIndx; /* sdu index to out standing sdu list in rbCb */
1497 uint32_t numSdus; /* number of sdus in the outstanding sdu list */
1498 RlcOutStngSduInfo *outStngSduArr; /* Outstanding sdu list */
1501 uint32_t totlSduCnt = 0;
1503 uint8_t timeAddedFlag;
1505 volatile uint32_t startTime = 0;
1506 /*kw005.201 Code added for DL IP thruput measurement*/
1509 SStartTask(&startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1512 if(hqStaInd->tbId[tbIdx] >= RLC_INVALID_TBID)
1517 /* Find the L2 measurement tbCb to process DL Ip thruput*/
1518 l2MeasTb = ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]];
1519 if(l2MeasTb == NULLP)
1523 /* For each logical channel in the tbCb, process
1524 * and get the DL IP thruput */
1525 ackTime = SGetTtiCount();
1526 for(lcIdx = 0; ((lcIdx < l2MeasTb->numLcId) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1528 timeAddedFlag = FALSE;
1529 if((rlcRbCb = ueCb->lCh[l2MeasTb->sduInfo[lcIdx].lcId - 1].dlRbCb)
1534 /* fix for DL IP stop*/
1535 if (!gCb->u.dlCb->rlcL2Cb.measOn[rlcRbCb->qci]
1536 || (rlcRbCb->rlcId.rbType == CM_LTE_SRB))
1541 /* Get the outstanding SDUs using sdu index stored in Container sduList
1542 * and check for HARQ ACK/NACK */
1543 numSdus = l2MeasTb->sduInfo[lcIdx].numSdus;
1545 if ((numSdus >= RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1549 totlSduCnt += numSdus;
1551 if (RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb,rlcRbCb))
1553 for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1555 outStngSduArr =&(rlcRbCb->l2MeasIpThruput.dlIpTh.outStngSduArr[\
1556 l2MeasTb->sduInfo[lcIdx].sduIdx[sduIndx]]);
1557 if(hqStaInd->status[tbIdx] == TRUE)
1559 /* If ACK is for burst End Sdu Id set burstActive
1560 * to FALSE and accumulate time */
1561 if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId ==
1562 outStngSduArr->sduId) && (outStngSduArr->numTb == 1))
1564 rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1565 /*Update the l2Sts structure for calculating throughput*/
1566 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1567 += outStngSduArr->sduLen;
1569 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1570 += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1571 outStngSduArr->sduId = 0;
1572 outStngSduArr->sduLen = 0;
1573 outStngSduArr->numTb = 0;
1574 rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1577 /* If burst is active and this sdu is only transmitted in single TB then
1578 * accumulate volume and clear the outstanding sduList */
1579 if((rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE) &&
1580 (--(outStngSduArr->numTb) == 0))
1582 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1583 += outStngSduArr->sduLen;
1585 if(timeAddedFlag == FALSE)
1587 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1588 += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1589 rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime = glblTtiCnt;
1590 timeAddedFlag = TRUE;
1592 outStngSduArr->sduId = 0;
1593 outStngSduArr->sduLen = 0;
1595 }/* End of status == TRUE */
1598 if(rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE)
1600 if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId ==
1601 outStngSduArr->sduId))
1603 rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1604 rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1606 /* Clear the outstanding sdu list */
1607 outStngSduArr->sduId = 0;
1608 outStngSduArr->sduLen = 0;
1609 outStngSduArr->numTb = 0;
1616 for(lcIdx = 0; ((lcIdx < l2MeasTb->numLchInfo) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1618 if((rlcRbCb = ueCb->lCh[l2MeasTb->lchInfo[lcIdx].lcId - 1].dlRbCb)
1623 numSdus = l2MeasTb->lchInfo[lcIdx].numSdus;
1629 if ((numSdus > RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1634 if(hqStaInd->status[tbIdx] == TRUE)
1636 for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1638 delay = RLC_TIME_DIFF(ackTime,l2MeasTb->lchInfo[lcIdx].sduInfo[sduIndx].arvlTime);
1639 RLC_UPD_PDCP_L2_DLDELAY_STS(gCb,rlcRbCb, delay);
1641 /* Case of sduInfo not updated */
1642 if (totlSduCnt == 0)
1644 totlSduCnt = numSdus;
1646 RLC_UPD_L2_UU_LOSS_POS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1650 /* Case of sduInfo not updated */
1651 if (totlSduCnt == 0)
1653 totlSduCnt = numSdus;
1655 RLC_UPD_L2_UU_LOSS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1658 /* Free this tb, deallocate the memory */
1659 RLC_FREE(gCb, l2MeasTb, sizeof(RlcL2MeasTb));
1660 ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]] = NULLP;
1663 SStopTask(startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1666 }/* end of rlcUtlProcHarqInd */
1670 * @brief Handler for Sending L2 Measurement confirm.
1674 * This function sends a consolidates the mesaurements taken during
1675 * this time and sends the confirm .
1677 * @param[in] measEvtCb Measurement Event Control Block.
1684 S16 rlcUtlSndDlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
1687 RlcL2MeasCb *measCb = NULLP;
1688 RlcL2MeasCfmEvt measCfmEvt;
1694 /* Discard new changes starts */
1697 /* Discard new changes ends */
1699 /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
1701 DU_LOG("\nDEBUG --> RLC_DL : rlcUtlSndL2MeasCfm(transId(%ld))", measEvtCb->transId);
1703 DU_LOG("\nDEBUG --> RLC_DL : rlcUtlSndL2MeasCfm(transId(%d))", measEvtCb->transId);
1706 /* Clean up the RB data structures */
1707 measCb = &measEvtCb->measCb;
1709 memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
1710 measCfmEvt.transId = measEvtCb->transId;
1712 measCfmEvt.measType = measCb->measType;
1713 measCfmEvt.status.status = LCM_PRIM_OK;
1714 measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
1716 if(measCb->measType & LKW_L2MEAS_DL_IP)
1718 RlcL2MeasCbUeMeasInfo *pUeInfoLstCb = measCb->val.ipThMeas.ueInfoLst;
1719 RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
1721 for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)
1723 pUeInfoLstCfm[cfmIdx].numCfm = 0;
1724 if (pUeInfoLstCb[cntr].isValid == TRUE)
1726 pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
1727 pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
1728 for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
1730 qci = pUeInfoLstCb[cntr].qci[qciIdx];
1731 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
1733 dlDataVol = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation;
1734 dlTime = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation;
1736 if((0 == dlTime) || !(gCb->u.dlCb->rlcL2Cb.measOn[qci] & LKW_L2MEAS_DL_IP) )
1738 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 0;
1742 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut =
1743 (dlDataVol / dlTime);
1745 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut *= 8;
1747 /* Reset the values after reporting to Application */
1748 pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation = 0;
1749 pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation = 0;
1751 measCfmEvt.val.ipThMeas.ueInfoLst[cfmIdx].numCfm++;
1756 measCfmEvt.val.ipThMeas.numUes = cfmIdx;
1760 RlcL2Cntr *pMeasData = measCb->val.nonIpThMeas.measData;
1761 RlcL2MeasCfmNonIpThMeas *pMeasCfmNonIp = &measCfmEvt.val.nonIpThMeas;
1763 pMeasCfmNonIp->numCfm = 0;
1765 for(qciIdx = 0; qciIdx < LKW_MAX_QCI; qciIdx++)
1767 qci = measCb->val.nonIpThMeas.qci[qciIdx];
1770 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].qci = qci;
1772 if(measCb->measType & LKW_L2MEAS_UU_LOSS)
1774 dLoss = pMeasData[qci].uuLoss.dLoss;
1775 posPkts = pMeasData[qci].uuLoss.posPkts;
1776 if(((posPkts + dLoss) != 0))
1778 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.uuLoss =
1779 ((dLoss * 1000000) / (posPkts + dLoss));
1781 pMeasData[qci].uuLoss.dLoss = 0;
1782 pMeasData[qci].uuLoss.posPkts = 0;
1784 if(measCb->measType & LKW_L2MEAS_DL_DISC)
1787 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 0;
1788 if(pMeasData[qci].dlDisc.totSdus != 0)
1790 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate =
1791 (((pMeasData[qci].dlDisc.discSdus) * 1000000) / (pMeasData[qci].dlDisc.totSdus));
1794 pMeasData[qci].dlDisc.totSdus = 0;
1795 pMeasData[qci].dlDisc.discSdus = 0;
1797 if(measCb->measType & LKW_L2MEAS_DL_DELAY)
1799 if (pMeasData[qci].dlPjSduDelay.numSdus > 0)
1801 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlSduDelay =
1802 (pMeasData[qci].dlPjSduDelay.sduDelay / pMeasData[qci].dlPjSduDelay.numSdus);
1803 pMeasData[qci].dlPjSduDelay.sduDelay = 0;
1804 pMeasData[qci].dlPjSduDelay.numSdus = 0;
1807 pMeasCfmNonIp->numCfm++;
1811 /* Fix Klock warning */
1812 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
1814 } /* rlcUtlSndL2MeasCfm */
1817 * @brief Handler for Sending Negative confirm .
1821 * This function is called when the l2 measurement cannot be started
1822 * This function sends negative confirm for all the requests
1824 * @param[in] measReqEvt Measurement Req Structure
1831 S16 rlcUtlSndDlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
1834 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
1836 } /* kwUtlSndL2MeasNCfm */
1839 * @brief Handler for resetting the RB data structures
1843 * This function resets the RB data structure after the expiry of
1844 * measurement timer.
1846 * @param[in] measCb Measurement Control Block.
1852 Void rlcUtlResetDlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
1856 RlcDlUeCb *ueCb = NULL;
1860 if (measCb->measType & LKW_L2MEAS_DL_IP)
1862 for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
1864 if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
1866 for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
1868 if (measType & LKW_L2MEAS_DL_IP)
1870 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.volSummation = 0;
1871 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.timeSummation = 0;
1872 gCb->u.dlCb->rlcL2Cb.measOn[qciIdx] &= ~measType;
1876 if(ROK != rlcDbmFetchDlUeCb(gCb,measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
1877 measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
1887 /* for now the only meas should be DL discard in this case */
1888 if (measCb->measType & LKW_L2MEAS_DL_DISC)
1891 for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
1893 uint8_t qciVal = measCb->val.nonIpThMeas.qci[i];
1895 measCb->val.nonIpThMeas.measData[qciVal].dlDisc.discSdus = 0;
1896 measCb->val.nonIpThMeas.measData[qciVal].dlDisc.totSdus = 0;
1900 if (measCb->measType & LKW_L2MEAS_DL_DELAY)
1903 for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
1905 uint8_t qciVal = measCb->val.nonIpThMeas.qci[i];
1907 measCb->val.nonIpThMeas.measData[qciVal].dlPjSduDelay.sduDelay = 0;
1910 measCb->val.nonIpThMeas.numQci = 0;
1912 } /* rlcUtlResetDlL2MeasInRlcRb */
1915 static Void dumpRLCDlRbInformation(RlcDlRbCb* dlRbCb)
1917 if(dlRbCb->mode == RLC_MODE_UM)
1919 DU_LOG("\nDEBUG --> RLC_DL : UM Downlink UEID:%d CELLID:%d Q size = %d",
1921 dlRbCb->rlcId.cellId,
1922 (int)dlRbCb->m.umDl.sduQ.count);
1924 else if(dlRbCb->mode == RLC_MODE_AM)
1926 uint32_t j, numTxPdus=0;
1927 for(j = 0; j <= (RLC_AM_GET_WIN_SZ(dlRbCb->m.amDl.snLen)); j++)
1929 RlcTx *txBuf = rlcUtlGetTxBuf(dlRbCb->m.amDl.txBufLst, j);
1935 DU_LOG("\nDEBUG --> RLC_DL : AM Downlink UEID:%d CELLID:%d Sizes SDU Q = %d TX Q = %d ",
1937 dlRbCb->rlcId.cellId,
1938 (int)dlRbCb->m.amDl.sduQ.count,
1940 DU_LOG("\nDEBUG --> RLC_DL : AM Downlink UEID:%d CELLID:%d RETX Q= %d",
1942 dlRbCb->rlcId.cellId,
1943 (int)dlRbCb->m.amDl.retxLst.count);
1947 Void DumpRLCDlDebugInformation(Void)
1949 RlcCb* dlInst = rlcCb[1]; /* TODO : Check whether DL is 0 or 1 */
1951 RlcDlCb *dlCb = dlInst->u.dlCb;
1953 RlcDlUeCb *ueCb = NULLP;
1954 RTLIN_DUMP_DEBUG("RLC Information\n");
1955 RTLIN_DUMP_DEBUG("===============\n");
1956 /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
1957 while (ROK == cmHashListGetNext(&dlCb->ueLstCp,
1962 for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
1964 RlcDlRbCb* dlRbCb = ueCb->srbCb[i];
1965 if( dlRbCb != NULLP)
1967 dumpRLCDlRbInformation(dlRbCb);
1970 for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
1972 RlcDlRbCb* dlRbCb = ueCb->drbCb[i];
1973 if( dlRbCb != NULLP)
1975 dumpRLCDlRbInformation(dlRbCb);
1980 RlcDlDataToBeFreed* pToBeFreed = &dlCb->toBeFreed;
1982 RTLIN_DUMP_DEBUG("toBeFreed RETX list size = %d\n",(int)pToBeFreed->reTxLst.count);
1983 RTLIN_DUMP_DEBUG("toBeFreed TX list size = %d\n",(int)pToBeFreed->txLst.count);
1984 RTLIN_DUMP_DEBUG("toBeFreed SDU list size = %d\n",(int)pToBeFreed->sduLst.count);
1985 RTLIN_DUMP_DEBUG("toBeFreed RB list size = %d\n",(int)pToBeFreed->rbLst.count);
1991 * This function frees downlink memory
1999 void rlcUtlFreeDlMem( Void)
2001 rlcUtlFreeDlMemory(RLC_GET_RLCCB(RLC_DL_INST));
2007 * This function returns current time
2009 * @param[in] uint32_t
2015 void rlcUtlGetCurrTime(uint32_t *currTime)
2017 /* Need t define else part for PAL */
2018 *currTime = SGetTtiCount();
2021 #if defined(MAC_RLC_HARQ_STA_RBUF) || defined (SS_RBUF)
2023 void rlcUtlDlBatchProcHqStaInd( Void)
2025 /* Read from Ring Buffer and process PDCP packets */
2028 Void *elmIndx = NULLP;
2029 RguHarqStaInd *staInd = NULLP;
2031 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2032 isDatReqProcessed = TRUE;
2034 elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ);
2035 while(NULLP != elmIndx)
2037 staInd = (RguHarqStaInd *)elmIndx;
2038 RlcLiRguHqStaInd(&(staInd->pst), 0, &(staInd->hqStatusInd));
2042 SRngIncrRIndx(SS_RNG_BUF_MAC_HARQ);
2044 if((elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ)) == NULLP)
2046 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2047 isDatReqProcessed = FALSE;
2057 * @brief evaluate and trigger PDB based flow control to PDCP
2061 * @param[in] rbCb RB control block
2067 Void rlcUtlTrigPdbFlowCntrl(RlcCb *gCb,RlcDlRbCb *rbCb,uint32_t pktAdmitCnt)
2069 KwuFlowCntrlIndInfo *flowCntrlInfo;
2070 RlcKwuSapCb* rlckwuSap;
2072 rlckwuSap = gCb->u.dlCb->rlcKwuDlSap + RLC_UI_PDCP;
2074 RLC_SHRABL_STATIC_BUF_ALLOC(rlckwuSap->pst.region,
2075 rlckwuSap->pst.pool,
2077 sizeof(KwuFlowCntrlIndInfo));
2078 flowCntrlInfo->rlcId = rbCb->rlcId;
2079 flowCntrlInfo->pktAdmitCnt = pktAdmitCnt;
2080 RlcUiKwuFlowCntrlInd(&rlckwuSap->pst, rlckwuSap->suId, flowCntrlInfo);
2085 * @brief Store the DL buffer in hashList
2090 * Use the SN % binSize as key and store the received UL buffer
2091 * @param[in] txBufLst List CP array
2092 * @param[in] txBuf transmitted buffer
2093 * @param[in] sn sn of the received buffer
2098 void rlcUtlStoreTxBuf(CmLListCp *txBufLst, RlcTx *txBuf, RlcSn sn)
2102 hashKey = (sn % RLC_TX_BUF_BIN_SIZE );
2104 txBuf->lnk.node = (PTR)txBuf;
2105 cmLListAdd2Tail(&(txBufLst[hashKey]), &txBuf->lnk);
2108 } /* rlcUtlStoreRecBuf */
2112 * @brief Retrieve the DL buffer from the list
2117 * Use the SN % binSize as key and retrieve the DL buffer
2118 * @param[in] txBufLst List CP array
2119 * @param[in] sn sn of the transmitted buffer
2124 RlcTx* rlcUtlGetTxBuf(CmLListCp *txBufLst, RlcSn sn)
2127 CmLListCp *txBufLstCp;
2129 CmLList *node = NULLP;
2131 hashKey = (sn % RLC_TX_BUF_BIN_SIZE );
2133 txBufLstCp = &txBufLst[hashKey];
2134 CM_LLIST_FIRST_NODE(txBufLstCp, node);
2137 txBuf = (RlcTx *) node->node;
2142 CM_LLIST_NEXT_NODE(txBufLstCp, node);
2145 } /* rlcUtlStoreTxBuf */
2148 * @brief Delete the DL buffer from the list
2153 * Use the SN % binSize as key and retrieve the DL buffer
2154 * @param[in] txBufLst List CP array
2155 * @param[in] sn sn of the transmitted bffer
2160 Void rlcUtlDelTxBuf (CmLListCp *txBufLst,RlcTx *txBuf,RlcCb *gCb)
2163 CmLListCp *txBufLstCp;
2165 hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE );
2167 txBufLstCp = &txBufLst[hashKey];
2168 //DU_LOG("\nINFO --> RLC_DL : D-sn(%d)\n", txBuf->hdr.sn);
2169 cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2170 RLC_FREE(gCb, txBuf, sizeof(RlcTx));
2172 } /* rlcUtlDelTxBuf */
2176 * @brief Remove the DL buffer from the list
2181 * Use the SN % binSize as key and retrieve the DL buffer
2182 * @param[in] txBufLst List CP array
2183 * @param[in] sn sn of the transmitted bffer
2188 Void rlcUtlRemovTxBuf(CmLListCp *txBufLst,RlcTx *txBuf,RlcCb *gCb)
2191 CmLListCp *txBufLstCp;
2193 hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE );
2195 txBufLstCp = &txBufLst[hashKey];
2196 //DU_LOG("\nINFO --> RLC_DL : D-sn(%d)\n", txBuf->hdr.sn);
2197 cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2199 } /* rlcUtlRemovTxBuf */
2203 /********************************************************************30**
2205 **********************************************************************/