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
37 **********************************************************************/
38 static const char* RLOG_MODULE_NAME="UTL";
39 static int RLOG_MODULE_ID=2048;
40 static int RLOG_FILE_ID=209;
43 @brief RLC Utility Module
46 /* header (.h) include files */
48 #include "common_def.h"
49 /* kw005.201 added support for L2 Measurement */
53 #include "ckw.h" /* CKW defines */
54 #include "kwu.h" /* CKW defines */
55 #include "lkw.h" /* LKW defines */
56 #include "rgu.h" /* RGU defiens */
58 #include "kw_env.h" /* RLC environment options */
59 #include "kw.h" /* RLC defines */
60 #include "kw_err.h" /* Error defines */
64 /* extern (.x) include files */
65 #include "ckw.x" /* CKW includes */
66 #include "kwu.x" /* KWU includes */
67 #include "lkw.x" /* LKW inlcudes */
68 #include "rgu.x" /* RGU includes */
70 #include "kw.x" /* RLC includes */
71 #include "kw_udx.x" /* UDX interface includes */
72 #include "kw_dl.x" /* RLC downlink includes */
77 EXTERN SsRngBufCnt rngCb;
79 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS))
80 extern U32 isDatReqProcessed;
82 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_DL) /* for debugging purpose */
83 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)) || defined (SS_RBUF)
84 EXTERN void rlcUtlDlBatchProcHqStaInd ARGS ((Void));
86 Void ResetRLCStats(Void)
88 RlcCb* dlInst = rlcCb[1];
89 RlcCb* ulInst = rlcCb[0];
90 cmMemset((U8*)&gRlcStats, 0, sizeof(RLCStats));
91 cmMemset((U8*)&dlInst->genSts,0,sizeof(RlcGenSts));
92 cmMemset((U8*)&ulInst->genSts,0,sizeof(RlcGenSts));
96 Void PrintRLCStats(Void)
98 RlcCb* dlInst = rlcCb[1];
99 RlcCb* ulInst = rlcCb[0];
101 RLOG4(L_ALWAYS,"RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)",
102 dlInst->genSts.pdusSent,
103 dlInst->genSts.pdusRetx,
104 dlInst->genSts.protTimeOut,
105 dlInst->genSts.numSduDisc);
106 RLOG3(L_ALWAYS,"RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)",
107 ulInst->genSts.pdusRecv,
108 ulInst->genSts.unexpPdusRecv,
109 ulInst->genSts.errorPdusRecv);
110 RLOG4(L_ALWAYS,"RLC Stats: AMDL: "
111 "StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu ",
112 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu,
113 gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
114 RLOG3(L_ALWAYS,"RLC Stats: AMDL: "
115 "DRB:%lu MaxRetx:%lu RetransPdus:%lu",
116 gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
117 gRlcStats.amRlcStats.numDLRetransPdus);
118 RLOG4(L_ALWAYS,"RLC Stats: AMUL: "
119 " PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu ",
120 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires,
121 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
123 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)\n",
124 dlInst->genSts.pdusSent,
125 dlInst->genSts.pdusRetx,
126 dlInst->genSts.protTimeOut,
127 dlInst->genSts.numSduDisc);
128 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)\n",
129 ulInst->genSts.pdusRecv,
130 ulInst->genSts.unexpPdusRecv,
131 ulInst->genSts.errorPdusRecv);
132 RTLIN_DUMP_DEBUG("RLC Stats:"
133 "AMDL: StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu DRB:%lu MaxRetx:%lu RetransPdus:%lu \n"
134 "AMUL: PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu \n",
135 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused,
136 gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
137 gRlcStats.amRlcStats.numDLRetransPdus, gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires,
138 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
141 Void PrintRLCStats(Void)
143 RlcCb* dlInst = rlcCb[1];
144 RlcCb* ulInst = rlcCb[0];
146 printf ("\n================================ RLC STATS ===========================\n");
147 RLOG4(L_ALWAYS,"RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)",
148 dlInst->genSts.pdusSent,
149 dlInst->genSts.pdusRetx,
150 dlInst->genSts.protTimeOut,
151 dlInst->genSts.numSduDisc);
152 RLOG3(L_ALWAYS,"RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)",
153 ulInst->genSts.pdusRecv,
154 ulInst->genSts.unexpPdusRecv,
155 ulInst->genSts.errorPdusRecv);
156 RLOG4(L_ALWAYS,"RLC Stats: AMDL: "
157 "StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu ",
158 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu,
159 gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
160 RLOG3(L_ALWAYS,"RLC Stats: AMDL: "
161 "DRB:%lu MaxRetx:%lu RetransPdus:%lu",
162 gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx,
163 gRlcStats.amRlcStats.numDLRetransPdus);
164 RLOG4(L_ALWAYS,"RLC Stats: AMUL: "
165 " PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu ",
166 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires,
167 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
168 /* RTLIN_DUMP_DEBUG("AM RLC Stats:"
169 "AMDL: SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) MaxRetx:(%u) WindowStalls: (%u) \n"
170 "AMUL: DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx :(%u) \n",
171 gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
172 gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmMaxRetx, gRlcStats.amRlcStats.numRlcAmCellWinStall,
173 gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
174 gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
176 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%d), PdusRext = (%d), TimeOut = (%d), SduDiscarded = (%d)\n",
177 dlInst->genSts.pdusSent,
178 dlInst->genSts.pdusRetx,
179 dlInst->genSts.protTimeOut,
180 dlInst->genSts.numSduDisc);
181 RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%d), unexpPdus = (%d), errorPdus = (%d)\n",
182 ulInst->genSts.pdusRecv,
183 ulInst->genSts.unexpPdusRecv,
184 ulInst->genSts.errorPdusRecv);
185 RTLIN_DUMP_DEBUG("AMDL: StaPduSent:%u NacksInStaPdu:%u BytesUnused:%u PollTimerExpires SRB:%u DRB:%u MaxRetx:%u RetransPdus:%u \n"
186 " SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) WindowStalls: (%u) \n"
188 "AMUL: PdusDiscarded:%u ReOrdTimerExpires:%u StaPduRcvd:%u NackInStaPduRcvd:%u \n"
189 " DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx:(%u) \n",
190 gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused,
191 gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb,
192 gRlcStats.amRlcStats.numDLMaxRetx, gRlcStats.amRlcStats.numDLRetransPdus,
193 gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
194 gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmCellWinStall,
195 gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires,
196 gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd,
197 gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
198 gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
202 /*******************************************************************
205 * Handler for storing all DL PDU Info into RLC-MAC interface
206 * struct and sending to lower interface
209 * This function stores DL PDU info for all logical channels
210 * of per UE grant per TTI and sends to MAC
212 * Function : RlcLiRguDDatReq
215 * @return ROK - success
218 * ****************************************************************/
224 RguDDatReqInfo *datReqInfo
227 S16 RlcLiRguDDatReq(post, spId, datReqInfo)
230 RguDDatReqInfo *datReqInfo;
233 U8 ueIdx; /* UE info list iterator */
234 U8 tbIdx; /* TB info list iterator */
235 U8 lchIdx; /* Lch info list iterator */
236 U8 pduIdx; /* RLC PDU list iterator */
237 RguDDatReqPerUe datPerUe; /* DL data info per UE */
238 RguDatReqTb datPerTb; /* DL data info per TB */
239 RguLchDatReq datPerLch; /* DL data info per Lch */
240 RlcMacData *dlData; /* DL data to be sent to MAC */
242 TRC3(RlcLiRguDDatReq)
245 RLC_ALLOC_SHRABL_BUF(post->region, post->pool,
246 dlData, sizeof(RlcMacData));
247 #if (ERRCLASS & ERRCLS_ADD_RES)
248 if ( datReqInfo == NULLP )
250 RLOG0(L_FATAL,"Memory allocation failed");
253 #endif /* ERRCLASS & ERRCLS_ADD_RES */
255 for(ueIdx = 0; ueIdx < datReqInfo->nmbOfUeGrantPerTti; ueIdx++)
257 datPerUe = datReqInfo->datReq[ueIdx];
259 cmMemset((U8 *)dlData, 0, sizeof(RlcMacData));
261 dlData->cellId = datReqInfo->cellId;
262 dlData->rnti = datPerUe.rnti;
263 //dlData->timeToTx = datPerUe.transId; /* Derive timing info from transId */
266 for(tbIdx = 0; tbIdx < datPerUe.nmbOfTbs; tbIdx++)
268 datPerTb = datPerUe.datReqTb[tbIdx];
269 for(lchIdx = 0; lchIdx < datPerTb.nmbLch; lchIdx++)
271 datPerLch = datPerTb.lchData[lchIdx];
272 for(pduIdx = 0; pduIdx < datPerLch.pdu.numPdu; pduIdx++)
274 dlData->pduInfo[dlData->numPdu].commCh = FALSE;
275 dlData->pduInfo[dlData->numPdu].lcId = datPerLch.lcId;
276 dlData->pduInfo[dlData->numPdu].pduBuf = datPerLch.pdu.mBuf[pduIdx];
279 }/* For Data per Lch */
280 }/* For Data per Tb */
281 RlcMacSendDlData(post, spId, dlData);
282 } /* For Data per UE */
284 /* Check if to be freed here */
286 RLC_FREE_SHRABL_BUF(post->region,
288 datReqInfo, sizeof(RguDDatReqInfo));
291 }/* End of RlcLiRguDDatReq */
296 * Handler for sending the data to multiple logical channels of a UE
299 * This function sends the data for one or more logical channels
300 * after processing the SDUs and forming the PDUs.It calls
301 * UMM or AMM functions to form the PDUs for the requested sizes
304 * @param[in] gCb RLC instance Control block
305 * @param[in] staIndInfo Status Indication Information containing the
306 * size of PDU(s) for one or more logical channels
318 KwDStaIndInfo *staIndInfo
321 S16 rlcUtlSndToLi(gCb, suId, staIndInfo)
324 KwDStaIndInfo *staIndInfo;
327 RlcDlUeCb *ueCb; /* UE control block */
328 U32 count; /* Loop Counter */
329 U32 numTb; /* Number of Tbs */
330 RlcDlRbCb *rbCb; /* RB Control Block */
331 RlcDatReq datReq; /* PDUs Information */
332 RguDDatReqInfo *datReqInfo; /* Data Request Information */
333 RlcRguSapCb *rguSap; /* MAC SAP CB */
334 U32 totNumPdu; /* Total number of PDUS */
335 RguStaIndTb *staIndTb = NULLP;
336 RguDatReqTb *datReqTb = NULLP;
337 RguDStaIndPerUe *staInd = NULLP;
339 U32 grantPerLch[RGU_MAX_LC] = {0};
341 /* kw005.201 added support for L2 Measurement */
342 #ifdef LTE_L2_MEAS_LOSS_DELAY
345 #endif /* LTE_L2_MEAS */
349 U32 staIndSz=0,datIndSz = 0;
354 RLC_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap->pst.region,
355 gCb->u.dlCb->rguDlSap->pst.pool,
356 datReqInfo,sizeof(RguDDatReqInfo));
357 #if (ERRCLASS & ERRCLS_ADD_RES)
358 if ( datReqInfo == NULLP )
360 RLOG_ARG0(L_FATAL,DBG_CELLID,staIndInfo->cellId,
361 "Memory allocation failed");
364 #endif /* ERRCLASS & ERRCLS_ADD_RES */
365 for(idx = 0; idx < staIndInfo->nmbOfUeGrantPerTti; idx++)
367 staInd = &staIndInfo->staInd[idx];
368 /* Fetch Ue control block */
369 if(ROK != rlcDbmFetchDlUeCb(gCb,staInd->rnti,staIndInfo->cellId,&ueCb))
371 /* Fetch UeCb failed */
372 RLOG_ARG1(L_ERROR, DBG_CELLID,staIndInfo->cellId,
373 "UeId[%u]:ueCb not found",
375 /* If ueCb is not found for current rnti then continue to look for next rnti*/
378 /* kw002.201 Removed the allocation of RlcDatReq */
379 /* kw004.201 Used SSI function to initialize the variable */
380 cmMemset( (U8 *)&datReq, 0, sizeof(RlcDatReq) );
382 for (numTb = 0; numTb < staInd->nmbOfTbs; numTb++)
384 staIndTb = &(staInd->staIndTb[numTb]);
385 datReqTb = &(datReqInfo->datReq[idx].datReqTb[numTb]);
387 ueCb->tbIdx = (ueCb->tbIdx+1) % RLC_MAX_TB_PER_UE;
389 for (count = 0;count < staIndTb->nmbLch; count++)
392 /*Calculate the total grant size from MAC */
393 if((staIndTb->lchStaInd[count].lcId >= RGU_MAX_LC)
394 || (staIndTb->lchStaInd[count].lcId == 0))
396 /* TODO : Need to figure out why this is happening */
401 grantPerLch[staIndTb->lchStaInd[count].lcId] += staIndTb->lchStaInd[count].totBufSize;
404 rbCb = ueCb->lCh[staIndTb->lchStaInd[count].lcId - 1].dlRbCb;
406 if (rbCb && (!rlcDlUtlIsReestInProgress(rbCb)))
409 staIndSz += staIndTb->lchStaInd[count].totBufSize;
410 datReq.pduSz = staIndTb->lchStaInd[count].totBufSize;
412 datReq.totMacGrant = grantPerLch[staIndTb->lchStaInd[count].lcId];
414 rlcUtlGetCurrTime(&datReq.boRep.oldestSduArrTime);
415 if ( CM_LTE_MODE_UM == rbCb->mode )
417 rlcUmmProcessSdus(gCb,rbCb,&datReq);
419 else if ( CM_LTE_MODE_AM == rbCb->mode )
421 rlcAmmProcessSdus(gCb,rbCb,&datReq,staInd->fillCtrlPdu);
424 grantPerLch[staIndTb->lchStaInd[count].lcId] = datReq.totMacGrant;
426 if ( 0 == datReq.pduInfo.numPdu )
430 totNumPdu += datReq.pduInfo.numPdu;
431 cmMemcpy((U8 *)(&(datReqTb->lchData[count].pdu)),
432 (U8 *)(&(datReq.pduInfo)),sizeof(KwPduInfo));
436 for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
439 SFndLenMsg(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
442 datReqTb->lchData[count].setMaxUlPrio = FALSE;
443 if (RLC_AM_IS_POLL_BIT_SET(AMDL) &&
444 (AMDL.sduQ.count > 1))
446 /* Poll bit is set indicate to MAC*/
447 datReqTb->lchData[count].setMaxUlPrio = TRUE;
449 datReqTb->lchData[count].boReport.bo = datReq.boRep.bo;
452 datReqTb->lchData[count].boReport.estRlcHdrSz =
453 datReq.boRep.estHdrSz;
454 datReqTb->lchData[count].boReport.staPduPrsnt =
455 datReq.boRep.staPduPrsnt;
456 #endif /* CCPU_OPT */
457 datReqTb->lchData[count].boReport.staPduBo =
458 datReq.boRep.staPduBo;
459 datReqTb->lchData[count].lcId = staIndTb->lchStaInd[count].lcId;
462 /* Set if Bearer is UM */
463 if ( CM_LTE_MODE_UM == rbCb->mode )
465 datReqTb->lchData[count].freeBuff = TRUE;
469 datReqTb->lchData[count].freeBuff = FALSE;
473 /* kw005.201 added support for L2 Measurement */
474 #ifdef LTE_L2_MEAS_LOSS_DELAY
475 datReqTb->rguSnInfo->lchMap[count].lChId =
476 staIndTb->lchStaInd[count].lcId;
477 /* In some cases L2 Measurement for few of the lcId may be off,
478 * in this case we are assigning snList to 0xffff
480 for(snIdx1 = 0; snIdx1 < RGU_MAX_PDU; snIdx1++)
482 datReqTb->rguSnInfo->lchMap[count].snList[snIdx1] = 0xffff;
484 if(tbSnMap->numSn != 0)
487 for(snIdx1=tbSnMap->prevNumSn;snIdx1 < tbSnMap->numSn;snIdx1++)
489 datReqTb->rguSnInfo->lchMap[count].snList[snIdx2++] =
490 tbSnMap->snSduMap[snIdx1].sn;
492 tbSnMap->prevNumSn = tbSnMap->numSn;
495 datReqTb->lchData[count].boReport.oldestSduArrTime =
496 datReq.boRep.oldestSduArrTime;
497 /* kw004.201 Used SSI function to initialize the variable */
498 cmMemset( (U8 *)&datReq, 0, sizeof(RlcDatReq) );
502 if(ueCb->l2MeasTbCb[ueCb->tbIdx]!= NULLP)
504 datReqTb->tbId = ueCb->tbIdx;
508 datReqTb->tbId = RLC_INVALID_TBID;
511 datReqTb->nmbLch = staIndTb->nmbLch;
512 /*adding the check to make sure that lcId is not sent as 0
513 * when no data is there in datReq */
514 if ( 0 == totNumPdu )
516 datReqTb->lchData[0].lcId = staIndTb->lchStaInd[0].lcId;
518 /* kw005.201 added support for L2 Measurement */
519 #ifdef LTE_L2_MEAS_LOSS_DELAY
520 if(tbSnMap->numSn == 0)
522 RLC_FREE(tbSnMap,sizeof(RlcTbSnMap));
523 RLC_FREE(datReqTb->rguSnInfo,sizeof(RguSnMapInfo));
524 datReqTb->rguSnInfo = NULLP;
525 rlcCb.rlcL2Cb.curTbSnMap = NULLP;
526 datReqTb->snMapPres = FALSE;
530 cmHashListInsert(&(rlcCb.rlcL2Cb.tbHlCp),(PTR)tbSnMap,
531 (U8 *) &(tbSnMap->tbId), (U16)sizeof(tbSnMap->tbId));
532 rlcCb.rlcL2Cb.curTbSnMap = NULLP;
534 #endif /* LTE_L2_MEAS */
536 datReqInfo->datReq[idx].nmbOfTbs = staInd->nmbOfTbs;
537 datReqInfo->datReq[idx].transId = staInd->transId;
538 datReqInfo->datReq[idx].rnti = staInd->rnti;
540 datReqInfo->cellId = staIndInfo->cellId;
541 datReqInfo->nmbOfUeGrantPerTti = staIndInfo->nmbOfUeGrantPerTti;
542 /* If trace flag is enabled send the trace indication */
543 if(TRUE == gCb->init.trc )
545 /* Populate the trace params */
546 rlcLmmSendTrc(gCb,EVTRGUDDATREQ, NULLP);
549 rguSap = &(gCb->u.dlCb->rguDlSap[suId]);
551 RlcLiRguDDatReq(&rguSap->pst,rguSap->spId,datReqInfo);
558 * Handler for sending Status Response to MAC.
561 * This function is used by RLC entity for sending
562 * status response to MAC after receiving a SDU from
565 * @param[in] gCb RLC instance Control block
566 * @param[in] rbCb Radio Bearer Control Block
567 * @param[in] bo Buffer Occupancy
568 * @param[in] estHdrSz Estimated Header Size
569 * @param[in] staPduPrsnt Status PDU present or not
586 S16 rlcUtlSndDStaRsp(gCb,rbCb,bo,estHdrSz,staPduPrsnt,staPduBo)
595 RlcMacBOStatus boStatus; /* Buffer occupancy status information */
596 RlcRguSapCb *rguSap; /* MAC SAP Information */
597 TRC3(rlcUtlSndDStaRsp)
599 if ((rbCb->lastRprtdBoToMac > (U32)8000) && (rbCb->boUnRprtdCnt < (U32)5)
600 && (!staPduPrsnt) && ((CM_LTE_MODE_AM == rbCb->mode ) && (AMDL.nxtRetx == NULLP)))
602 rbCb->boUnRprtdCnt++;
607 rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
609 rbCb->boUnRprtdCnt = (U32)0;
610 rbCb->lastRprtdBoToMac = (U32)bo;
612 boStatus.cellId = rbCb->rlcId.cellId;
613 boStatus.rnti = rbCb->rlcId.ueId;
614 boStatus.commCh = FALSE;
615 boStatus.lcId = rbCb->lch.lChId;
618 /* If trace flag is enabled send the trace indication */
619 if(gCb->init.trc == TRUE)
621 /* Populate the trace params */
622 rlcLmmSendTrc(gCb, EVTRLCBOSTA, NULLP);
624 /* Send Status Response to MAC layer */
625 RlcMacSendBOStatus(&rguSap->pst,rguSap->spId,&boStatus);
634 * Handler for emptying the SDU queue.
637 * This function is used to empty the SDU queue when
638 * a re-establishment request is received from the
641 * @param[in] gCb RLC instance control block
642 * @param[in] rbCb Radio bearer control block
643 * @param[in] sduQ SDU queue to be emptied
647 /* kw005.201 added support for L2 Measurement */
648 #ifdef LTE_L2_MEAS_RLC
657 Void rlcUtlEmptySduQ(gCb,rbCb, sduQ)
670 Void rlcUtlEmptySduQ(gCb,sduQ)
676 #ifdef LTE_L2_MEAS_RLC
677 CmLListCp *sduSnMapQ; /* SDU Sequence number map queue */
678 CmLList *firstSduSnMap; /* First Node in SDU SnMap Queue */
679 RlcSduSnMap *sduSnMap; /* SDU Sn Map */
681 TRC2(rlcUtlEmptySduQ)
683 firstSduSnMap = NULLP;
687 sduSnMapQ = &rbCb->sduSnMapQ;
688 CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
692 sduSnMap = (RlcSduSnMap *)firstSduSnMap->node;
693 if(sduSnMap != NULLP)
695 cmLListDelFrm(&(rbCb->sduSnMapQ), &(sduSnMap->lstEnt));
696 RLC_FREE(sduSnMap, sizeof(RlcSduSnMap));
697 CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
701 CM_LLIST_NEXT_NODE(sduSnMapQ, firstSduSnMap);
711 * Handler for calculating the Length Indicator (LI) length for a SDU
714 * This function is used to calculate the LI (Length Indicator) length
715 * which has to be substracted from the pduSize to correctly match the
716 * formed PDU(s) size with the size requested by MAC.
718 * @param[in] gCb RLC instance control block
719 * @param[in] numLi Number of LIs already present
720 * @param[in] msgLen Size of the SDU
721 * @param[in/out] pduSz Size of the pDU to be formed
726 Void rlcUtlCalcLiForSdu
734 Void rlcUtlCalcLiForSdu(gCb,numLi,msgLen,pduSz)
741 TRC2(rlcUtlCalcLiForSdu)
743 if ( (*pduSz > msgLen) && (msgLen < RLC_2K_BYTE))
745 if(0 == (numLi & RLC_BIT0)) /* check if number of LIs are odd or even */
747 /* if number of LI's are even 2 bytes needed */
752 /* if number of LI's are odd one byte needed */
762 * Function to set that re-establishment has started for an RB
765 * This function is used to set the reestInProgress flag to TRUE.
766 * This also sets the estimated header size to 0 and sends bo as
767 * 0 to MAC so that RLC does not need to transmit any data.
768 * If the poll re-transmit timer is running for the RB;
771 * @param[in] gCb RLC instance control block
772 * @param[in] rbCb RB for which re-establishment has started
777 Void rlcDlUtlSetReestInProgressForRB
783 Void rlcDlUtlSetReestInProgressForRB(gCb,rbCb)
788 TRC2(rlcDlUtlSetReestInProgressForRB)
790 rbCb->reestInProgress = TRUE;
792 if(rbCb->mode == CM_LTE_MODE_AM )
794 rbCb->m.amDl.estHdrSz = 0;
796 if(rlcChkTmr(gCb, (PTR)rbCb, RLC_EVT_AMDL_POLL_RETX_TMR))
798 rlcStopTmr(gCb, (PTR)rbCb, RLC_EVT_AMDL_POLL_RETX_TMR);
803 rbCb->m.umDl.estHdrSz= 0;
806 rlcUtlSndDStaRsp(gCb, rbCb, 0, 0, FALSE,0);
814 * Function to check if re-establishment is ongoing for an RB
816 * @param[in] rbCb RB for which re-establishment is to be checked
819 * TRUE : Re-establishment is in progress
820 * FALSE : Re-establishment is not in progress
823 Bool rlcDlUtlIsReestInProgress
828 Bool rlcDlUtlIsReestInProgress(rbCb)
832 TRC2(rlcDlUtlSetReestInProgressForRB)
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
847 Void rlcDlUtlResetReestInProgress
852 Void rlcDlUtlResetReestInProgress(rbCb)
856 TRC2(rlcDlUtlSetReestInProgressForRB)
858 rbCb->reestInProgress = FALSE;
864 * Function to set that re-establishment has started for all the RBs
865 * of an UE; except for SRB1
867 * @detail: For SRB1 only the poll-retransmit timer is stopped
869 * @param[in] gCb RLC instance control block
870 * @param[in] ueCb UE for which re-establishment has started
875 Void rlcDlUtlSetReestInProgressForAllRBs
881 Void rlcDlUtlSetReestInProgressForAllRBs(gCb,ueCb)
888 TRC2(rlcDlUtlSetReestInProgressForAllRBs)
890 for(rbIdx = 0;rbIdx < RLC_MAX_SRB_PER_UE;rbIdx++)
892 if(ueCb->srbCb[rbIdx] != NULLP)
894 if(ueCb->srbCb[rbIdx]->rlcId.rbId != 1)
896 rlcDlUtlSetReestInProgressForRB(gCb,ueCb->srbCb[rbIdx]);
900 /* For SRB we just need to stop the poll re-transmit timer */
901 if(rlcChkTmr(gCb, (PTR)ueCb->srbCb[rbIdx], RLC_EVT_AMDL_POLL_RETX_TMR))
903 rlcStopTmr(gCb, (PTR)ueCb->srbCb[rbIdx], RLC_EVT_AMDL_POLL_RETX_TMR);
909 for(rbIdx = 0;rbIdx < RLC_MAX_DRB_PER_UE;rbIdx++)
911 if(ueCb->drbCb[rbIdx] != NULLP)
913 rlcDlUtlSetReestInProgressForRB(gCb,ueCb->drbCb[rbIdx]);
921 * @brief Function to increment number of SDUs transmitted
922 * in KWU SAP statistics
925 * @param[in] rlckwuSap KWU SAP in which to increment the counter
930 Void rlcUtlIncrementKwuStsSduTx
932 RlcKwuSapCb *rlckwuSap
935 Void rlcUtlIncrementKwuStsSduTx(rlckwuSap)
936 RlcKwuSapCb *rlckwuSap;
939 rlckwuSap->sts.sduTx++;
944 * @brief Function to increment number of bytes and PDUs transmitted
945 * in General statistics
948 * @param[in] genSts KWU SAP in which to increment the counter
949 * @param[in] pdu The PDU which is sent
954 Void rlcUtlIncrementGenStsBytesAndPdusSent
960 Void rlcUtlIncrementGenStsBytesAndPdusSent(genSts, pdu)
966 SFndLenMsg(pdu, &bytesSent);
967 genSts->bytesSent += bytesSent;
973 * @brief Function to initialize the data structures used to free memory
976 * @param[in] gCb RLC instance control block
977 * @param[out] toBeFreed Pointer to the freeing structure. This is
983 Void rlcUtlInitToBeFreed
986 RlcDlDataToBeFreed *toBeFreed
989 Void rlcUtlInitToBeFreed(gCb, toBeFreed)
991 RlcDlDataToBeFreed *toBeFreed;
994 cmLListInit(&(toBeFreed->sduLst));
995 cmLListInit(&(toBeFreed->rbLst));
996 cmLListInit(&(toBeFreed->reTxLst));
997 cmLListInit(&(toBeFreed->txLst));
1003 * @brief Function to initialize the DL self Pst structure
1006 * @param[in] gCb RLC instance control block
1011 Void rlcUtlInitializeSelfPst
1016 Void rlcUtlInitializeSelfPst(gCb)
1020 Pst *selfPst = &gCb->u.dlCb->selfPst;
1022 RLC_MEM_SET(selfPst, 0, sizeof(Pst));
1023 selfPst->srcProcId = SFndProcId();
1024 selfPst->dstProcId = SFndProcId();
1025 selfPst->dstEnt = gCb->init.ent;
1026 selfPst->dstInst = gCb->init.inst; /* this is for the DL instance */
1027 selfPst->srcEnt = gCb->init.ent;
1028 selfPst->srcInst = gCb->init.inst; /* DL instance will send to itself */
1029 selfPst->prior = PRIOR3;
1030 selfPst->event = UDX_EVT_DL_CLEANUP_MEM;
1034 * @brief Function to send a DL cleanup event
1037 * @param[in] gCb RLC instance control block
1042 Void rlcUtlRaiseDlCleanupEvent
1047 Void rlcUtlRaiseDlCleanupEvent(gCb)
1051 #ifdef KWSELFPSTDLCLEAN
1052 if(!gCb->u.dlCb->eventInQueue)
1054 SPstTsk(&gCb->u.dlCb->selfPst, gCb->u.dlCb->selfPstMBuf);
1055 gCb->u.dlCb->eventInQueue = TRUE;
1062 * @brief Function to add a SDU to the to be freed sdu list
1065 * @param[in] gCb RLC instance control block
1066 * @param[in] sdu SDU to be added to the list
1071 Void rlcUtlAddSduToBeFreedQueue
1077 Void rlcUtlAddSduToBeFreedQueue(gCb, sdu)
1082 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.sduLst), &(sdu->lstEnt));
1087 * @brief Function to add a re-transmitted pdu to the to be freed list
1090 * @param[in] gCb RLC instance control block
1091 * @param[in] retx Re-transmitted pdu to be added to the list
1096 Void rlcUtlAddReTxPduToBeFreedQueue
1102 Void rlcUtlAddReTxPduToBeFreedQueue(gCb, retx)
1107 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.reTxLst), &(retx->lstEnt));
1112 * @brief Function to add a transmitted pdu to the to be freed list
1115 * @param[in] gCb RLC instance control block
1116 * @param[in] pdu PDU to be added to the list
1121 Void rlcUtlAddTxPduToBeFreedQueue
1127 Void rlcUtlAddTxPduToBeFreedQueue(gCb, pdu)
1132 pdu->rlsLnk.node = (PTR)pdu;
1133 cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.txLst), &(pdu->rlsLnk));
1139 * function to free/release the Acknowledged mode RBCB buffers
1142 * This primitive Frees the Acknowledged Mode RbCb transmission Buffer,
1143 * retransmission Buffer and reciption Buffers
1145 * @param [in] gCb - RLC instance control block
1146 * @param [in] rbCb - Downlink RB Control Block
1147 * @param [in,out] toBeFreed - Number of buffers to be freed
1150 * - TRUE if more data to be freed
1151 * - FALSE if all the data has been freed
1154 PRIVATE Bool rlcUtlFreeDlAmRbMemory
1161 PRIVATE Bool rlcUtlFreeDlAmRbMemory(gCb, rbCb, toBeFreed)
1167 RlcRetx *retx; /* retransmission buffer */
1168 RlcSn mTxNext; /* send state variable */
1171 TRC2(rlcUtlFreeDlAmRbMemory)
1174 MODAMT(AMDL.txNext, mTxNext, AMDL.txNextAck,AMDL.snModMask);
1176 /* TODO : to be checked changed from <= to < */
1177 while ((0 < mTxNext) && *toBeFreed)
1179 txBuf = rlcUtlGetTxBuf(AMDL.txBufLst, AMDL.txNextAck);
1180 if (txBuf && txBuf->pduLst.first)
1182 while(txBuf->pduLst.first)
1184 RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(txBuf->pduLst.first->node);
1185 RLC_FREE_BUF(pduInfo->pdu);
1186 /* Delete node from the txBuf Pdu lst */
1187 cmLListDelFrm(&txBuf->pduLst, txBuf->pduLst.first);
1188 RLC_FREE_WC(gCb, pduInfo, sizeof(RlcDlPduInfo));
1190 rlcUtlDelTxBuf(AMDL.txBufLst, txBuf, gCb);
1191 if(gCb->u.dlCb->shutdownReceived == 0)
1196 AMDL.txNextAck = (AMDL.txNextAck + 1) & AMDL.snModMask;
1197 MODAMT(AMDL.txNext, mTxNext, AMDL.txNextAck,AMDL.snModMask);
1205 RLC_FREE(gCb,AMDL.txBufLst, (RLC_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
1208 RLC_LLIST_FIRST_RETX(AMDL.retxLst, retx);
1209 while (retx && (*toBeFreed)) /* Till to be freed becomes 0 */
1212 RLC_FREE_BUF(retx->seg);
1214 cmLListDelFrm(&AMDL.retxLst, &retx->lstEnt);
1215 RLC_FREE_WC(gCb, retx, sizeof(RlcRetx));
1217 RLC_LLIST_FIRST_RETX(AMDL.retxLst, retx);
1218 if(gCb->u.dlCb->shutdownReceived == 0)
1225 AMDL.nxtRetx = NULLP;
1227 /* clean up if there is info about STATUS PDU to be sent */
1231 udxPst = &gCb->u.dlCb->udxDlSap->pst;
1232 RLC_FREE_SHRABL_BUF_WC(udxPst->region,
1235 sizeof(RlcUdxDlStaPdu));
1236 AMDL.pStaPdu = NULLP;
1243 if(gCb->u.dlCb->shutdownReceived)
1252 * @brief Function to free memory from the DL instance
1255 * @param[in] gCb RLC instance control block
1260 Void rlcUtlFreeDlMemory
1265 Void rlcUtlFreeDlMemory(gCb)
1271 /* safety check, in case some event was still lying in the queue after
1272 the dlCb was deleted*/
1278 RlcDlDataToBeFreed* pToBeFreed = &gCb->u.dlCb->toBeFreed;
1280 if(gCb->u.dlCb->shutdownReceived)
1282 toBeFreed = pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count + pToBeFreed->rbLst.count;
1286 if ((pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count) > (3 * RLC_MAX_TO_BE_FREED))
1288 #if !defined(KWSELFPSTDLCLEAN) && defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
1289 if (isDatReqProcessed)
1291 toBeFreed = (2 *RLC_MAX_TO_BE_FREED);
1296 toBeFreed = (3 *RLC_MAX_TO_BE_FREED)/2;
1301 toBeFreed = RLC_MAX_TO_BE_FREED;
1306 gCb->u.dlCb->eventInQueue = FALSE; /* reset as we have received the event
1307 and are processing it */
1309 /* Free from the ReTx list */
1310 lst = &pToBeFreed->reTxLst;
1312 while((lst->first) && toBeFreed && (pToBeFreed->reTxLst.count > 100))
1314 while((lst->first) && toBeFreed)
1317 RlcRetx* seg = (RlcRetx *)(lst->first->node);
1318 cmLListDelFrm(lst, lst->first);
1319 RLC_FREE_BUF_WC(seg->seg);
1320 RLC_FREE_WC(gCb,seg, sizeof(RlcRetx));
1324 /* Free from the Tx list */
1325 lst = &pToBeFreed->txLst;
1327 while((lst->first) && toBeFreed && (pToBeFreed->txLst.count > 100))
1329 while((lst->first) && toBeFreed)
1332 RlcTx* pdu = (RlcTx *)(lst->first->node);
1333 cmLListDelFrm(lst, lst->first);
1334 while(pdu->pduLst.first)
1336 RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(pdu->pduLst.first->node);
1338 cmLListDelFrm(&pdu->pduLst, pdu->pduLst.first);
1339 RLC_FREE_BUF_WC(pduInfo->pdu);
1340 RLC_FREE_WC(gCb, pduInfo, sizeof(RlcDlPduInfo));
1342 RLC_FREE_WC(gCb,pdu, sizeof(RlcTx));
1346 /* Free from the SDU queue */
1347 lst = &pToBeFreed->sduLst;
1349 while((lst->first) && toBeFreed && (pToBeFreed->sduLst.count > 100))
1351 while((lst->first) && toBeFreed)
1354 RlcSdu* sdu = (RlcSdu *)(lst->first->node);
1355 RLC_RMV_SDU(gCb, lst, sdu);
1359 /* Free from the RBs */
1360 lst = &pToBeFreed->rbLst;
1362 while((lst->first) && toBeFreed && (pToBeFreed->rbLst.count > 100))
1364 while((lst->first) && toBeFreed)
1367 RlcDlRbCb* rbCb = (RlcDlRbCb *)(lst->first->node);
1368 Bool moreToBeFreed = rlcUtlFreeDlAmRbMemory(gCb, rbCb,&toBeFreed);
1371 cmLListDelFrm(lst, lst->first);
1372 RLC_FREE_WC(gCb, rbCb, sizeof(RlcDlRbCb));
1376 if ((toBeFreed == 0) && !(gCb->u.dlCb->shutdownReceived))
1378 rlcUtlRaiseDlCleanupEvent(gCb);
1388 * @brief Function to initialise measurement
1392 * @param[in] gCb RLC Instance Control Block
1397 S16 rlcUtlL2MeasDlInit(RlcCb *gCb)
1401 gCb->u.dlCb->rlcL2Cb.rlcNumMeas=0;
1402 for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
1404 cmMemset((U8 *)&(gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
1406 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DISC].measCb.measType = LKW_L2MEAS_DL_DISC;
1407 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_IP].measCb.measType = LKW_L2MEAS_DL_IP;
1408 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DELAY].measCb.measType= LKW_L2MEAS_DL_DELAY;
1409 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UU_LOSS].measCb.measType= LKW_L2MEAS_UU_LOSS;
1410 gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_ACT_UE].measCb.measType= LKW_L2MEAS_ACT_UE;
1416 * @brief Function to detect the data Burst start Condition in a DTCH
1420 * @param[in] rbCb RB control block
1421 * @param[in] contSduLst Array of Contained SDUs in the DTCH
1422 * @param[in] dataVol Available data in the DTCH
1423 * @param[in] schPduSz Total grant Size given by MAC
1429 Void rlcUtlUpdateBurstSdus
1433 RlcContSduLst *contSduLst,
1438 Void rlcUtlUpdateBurstSdus (gCb, rbCb, contSduLst, dataVol, schPduSz)
1441 RlcContSduLst *contSduLst;
1447 RlcL2MeasDlIpTh *l2MeasDlIpThruput = NULLP;
1448 RlcL2MeasTb *l2MeasTb = NULLP;
1451 VOLATILE U32 startTime = 0;
1452 RlcContSduLst *dstContSduLst;
1453 TRC2(rlcUtlUpdateBurstSdus)
1457 SStartTask(&startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1459 l2MeasDlIpThruput = &rbCb->l2MeasIpThruput.dlIpTh;
1461 if(RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb, rbCb))
1463 if(dataVol > schPduSz)
1465 if(l2MeasDlIpThruput->isBurstAct == FALSE)
1467 l2MeasDlIpThruput->burstStartTime = glblTtiCnt;
1468 l2MeasDlIpThruput->isBurstAct = TRUE;
1469 l2MeasDlIpThruput->burstEndSduId = 0;
1472 { /* This is the case when another burst started before RLC gets the
1473 l2MeasDlIpThruput->burstEndSduId = 0; */
1477 { /* Store the burstEndSduId here */
1478 if((l2MeasDlIpThruput->isBurstAct == TRUE) &&
1479 (!l2MeasDlIpThruput->burstEndSduId))
1481 l2MeasDlIpThruput->burstEndSduId =
1482 l2MeasDlIpThruput->outStngSduArr[l2MeasDlIpThruput->lastSduIdx].sduId;
1485 if(l2MeasDlIpThruput->isBurstAct == TRUE)
1487 l2MeasTb = rlcUtlGetCurMeasTb(gCb,rbCb);
1488 /* Get the lChId from index 0, because index 0 is always for DL */
1489 if(l2MeasTb->numLcId >= RLC_MAX_ACTV_DRB)
1494 l2MeasTb->sduInfo[l2MeasTb->numLcId].lcId = rbCb->lch.lChId;
1495 /* Copy all the sduIdx from sduInfo to tb sduInfo */
1496 currTbIdx = l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus;
1497 dstContSduLst = &l2MeasTb->sduInfo[l2MeasTb->numLcId];
1499 for(idx = 0; ((idx < contSduLst->numSdus)
1500 && (currTbIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)) ; idx++)
1502 dstContSduLst->sduIdx[currTbIdx++] = contSduLst->sduIdx[idx];
1504 l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus += idx;
1505 l2MeasTb->numLcId++;
1506 }/* End of isBurstAct */
1507 }/* End of if measOn */
1510 SStopTask(startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1515 * This function is used to store locally the sduIdx of the sdu in the
1516 * outstanding SDU array
1519 * Stores the Sdu Idx in the contained SDU Array and increments
1520 * the num contained Sdus
1522 * @param[in] sduIdx the Index of the SDU in the outstanding SDU array
1523 * @param[out] contSduLst This stores the indices of the SDUs
1528 Void rlcUtlUpdateContainedSduLst
1531 RlcContSduLst *contSduLst
1534 Void rlcUtlUpdateContainedSduLst(sduIdx, contSduLst)
1536 RlcContSduLst *contSduLst;
1539 if (contSduLst->numSdus < RLC_L2MEAS_MAX_OUTSTNGSDU)
1541 contSduLst->sduIdx[contSduLst->numSdus] = sduIdx;
1542 contSduLst->numSdus++;
1549 * This function is used to store the sduId of the sdu in the
1550 * outstanding SDU array
1553 * Stores the Sdu Id in the outstanding SDU Array and increments
1554 * the num contained Sdus
1556 * @param[out] dlIpThPut The structure in which the outstanding sdus are
1558 * @param[in] sduIdx The Idx at which the sdu ID is stored
1559 * @param[in] sduLen The size if sdu in bytes
1560 * @param[in] newIdx Indicates if the sdu is already present in the
1566 Void rlcUtlUpdateOutStandingSduLst
1568 RlcL2MeasDlIpTh *dlIpThPut,
1575 Void rlcUtlUpdateOutStandingSduLst(dlIpThPut, sduIdx, sduLen, sduId, newIdx)
1576 RlcL2MeasDlIpTh *dlIpThPut;
1583 if (sduIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)
1587 dlIpThPut->outStngSduArr[sduIdx].numTb = 0;
1589 dlIpThPut->outStngSduArr[sduIdx].numTb++;
1590 dlIpThPut->outStngSduArr[sduIdx].sduId = sduId;
1591 dlIpThPut->outStngSduArr[sduIdx].sduLen = sduLen;
1596 RlcL2MeasTb * rlcUtlGetCurMeasTb
1602 RlcL2MeasTb * rlcUtlGetCurMeasTb(gCb, rbCb)
1607 RlcL2MeasTb *curL2MeasTb;
1610 TRC3(rlcUtlGetCurMeasTb)
1612 if((curL2MeasTb = rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx]) == NULLP)
1614 /* Intentionally avoiding the RLC_ALLOC macro to avoid memset */
1615 if (SGetSBuf(gCb->init.region,
1617 (Data **)&curL2MeasTb,
1618 (Size)sizeof(RlcL2MeasTb)) != ROK)
1622 rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx] = curL2MeasTb;
1623 /* Initialize the Meas Tb details */
1624 curL2MeasTb->numLcId = 0;
1625 curL2MeasTb->numLchInfo = 0;
1626 curL2MeasTb->txSegSduCnt = 0;
1627 for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1629 curL2MeasTb->sduInfo[idx].numSdus = 0;
1631 for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1633 curL2MeasTb->lchInfo[idx].numSdus = 0;
1636 return (curL2MeasTb);
1642 * @brief Handler for Processing harq status indication
1646 * This function is called when the MAC sends a harq ind Mesage.
1647 * This is used only for UuLoss and Dl Delay and DL Ipthoughput
1650 * @param[in] staInd Harq status indication received from MAC.
1651 * @param[in] ueCb UeCb corresponding to the Tb Id.
1652 * @param[in] tbIdx TB index, 0 for SISO and 0,1 for MIMO.
1660 S16 rlcUtlProcHarqInd
1663 RguHarqStatusInd *hqStaInd,
1668 S16 rlcUtlProcHarqInd(gCb, hqStaInd, ueCb, tbIdx)
1670 RguHarqStatusInd *hqStaInd;
1676 RlcDlRbCb *rlcRbCb; /* KW Control Block */
1677 RlcL2MeasTb *l2MeasTb = NULLP; /* Measurement TbCb */
1678 U8 lcIdx; /* Logical channel id index */
1679 U8 sduIndx; /* sdu index to out standing sdu list in rbCb */
1680 U32 numSdus; /* number of sdus in the outstanding sdu list */
1681 RlcOutStngSduInfo *outStngSduArr; /* Outstanding sdu list */
1688 VOLATILE U32 startTime = 0;
1689 /*kw005.201 Code added for DL IP thruput measurement*/
1691 TRC3(rlcUtlProcHarqInd)
1694 SStartTask(&startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1697 if(hqStaInd->tbId[tbIdx] >= RLC_INVALID_TBID)
1702 /* Find the L2 measurement tbCb to process DL Ip thruput*/
1703 l2MeasTb = ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]];
1704 if(l2MeasTb == NULLP)
1708 /* For each logical channel in the tbCb, process
1709 * and get the DL IP thruput */
1710 ackTime = SGetTtiCount();
1711 for(lcIdx = 0; ((lcIdx < l2MeasTb->numLcId) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1713 timeAddedFlag = FALSE;
1714 if((rlcRbCb = ueCb->lCh[l2MeasTb->sduInfo[lcIdx].lcId - 1].dlRbCb)
1719 /* fix for DL IP stop*/
1720 if (!gCb->u.dlCb->rlcL2Cb.measOn[rlcRbCb->qci]
1721 || (rlcRbCb->rlcId.rbType == CM_LTE_SRB))
1726 /* Get the outstanding SDUs using sdu index stored in Container sduList
1727 * and check for HARQ ACK/NACK */
1728 numSdus = l2MeasTb->sduInfo[lcIdx].numSdus;
1730 if ((numSdus >= RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1734 totlSduCnt += numSdus;
1736 if (RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb,rlcRbCb))
1738 for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1740 outStngSduArr =&(rlcRbCb->l2MeasIpThruput.dlIpTh.outStngSduArr[\
1741 l2MeasTb->sduInfo[lcIdx].sduIdx[sduIndx]]);
1742 if(hqStaInd->status[tbIdx] == TRUE)
1744 /* If ACK is for burst End Sdu Id set burstActive
1745 * to FALSE and accumulate time */
1746 if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId ==
1747 outStngSduArr->sduId) && (outStngSduArr->numTb == 1))
1749 rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1750 /*Update the l2Sts structure for calculating throughput*/
1751 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1752 += outStngSduArr->sduLen;
1754 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1755 += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1756 outStngSduArr->sduId = 0;
1757 outStngSduArr->sduLen = 0;
1758 outStngSduArr->numTb = 0;
1759 rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1762 /* If burst is active and this sdu is only transmitted in single TB then
1763 * accumulate volume and clear the outstanding sduList */
1764 if((rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE) &&
1765 (--(outStngSduArr->numTb) == 0))
1767 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1768 += outStngSduArr->sduLen;
1770 if(timeAddedFlag == FALSE)
1772 rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1773 += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1774 rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime = glblTtiCnt;
1775 timeAddedFlag = TRUE;
1777 outStngSduArr->sduId = 0;
1778 outStngSduArr->sduLen = 0;
1780 }/* End of status == TRUE */
1783 if(rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE)
1785 if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId ==
1786 outStngSduArr->sduId))
1788 rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1789 rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1791 /* Clear the outstanding sdu list */
1792 outStngSduArr->sduId = 0;
1793 outStngSduArr->sduLen = 0;
1794 outStngSduArr->numTb = 0;
1801 for(lcIdx = 0; ((lcIdx < l2MeasTb->numLchInfo) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1803 if((rlcRbCb = ueCb->lCh[l2MeasTb->lchInfo[lcIdx].lcId - 1].dlRbCb)
1808 numSdus = l2MeasTb->lchInfo[lcIdx].numSdus;
1814 if ((numSdus > RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1819 if(hqStaInd->status[tbIdx] == TRUE)
1821 for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1823 delay = RLC_TIME_DIFF(ackTime,l2MeasTb->lchInfo[lcIdx].sduInfo[sduIndx].arvlTime);
1824 RLC_UPD_PDCP_L2_DLDELAY_STS(gCb,rlcRbCb, delay);
1826 /* Case of sduInfo not updated */
1827 if (totlSduCnt == 0)
1829 totlSduCnt = numSdus;
1831 RLC_UPD_L2_UU_LOSS_POS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1835 /* Case of sduInfo not updated */
1836 if (totlSduCnt == 0)
1838 totlSduCnt = numSdus;
1840 RLC_UPD_L2_UU_LOSS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1843 /* Free this tb, deallocate the memory */
1844 RLC_FREE(gCb, l2MeasTb, sizeof(RlcL2MeasTb));
1845 ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]] = NULLP;
1848 SStopTask(startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1851 }/* end of rlcUtlProcHarqInd */
1855 * @brief Handler for Sending L2 Measurement confirm.
1859 * This function sends a consolidates the mesaurements taken during
1860 * this time and sends the confirm .
1862 * @param[in] measEvtCb Measurement Event Control Block.
1870 S16 rlcUtlSndDlL2MeasCfm
1873 RlcL2MeasEvtCb *measEvtCb
1876 S16 rlcUtlSndDlL2MeasCfm(gCb, measEvtCb)
1878 RlcL2MeasEvtCb *measEvtCb;
1882 RlcL2MeasCb *measCb = NULLP;
1883 RlcL2MeasCfmEvt measCfmEvt;
1890 /* Discard new changes starts */
1893 /* Discard new changes ends */
1895 TRC3(rlcUtlSndL2MeasCfm)
1897 /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
1899 RLOG1(L_DEBUG,"rlcUtlSndL2MeasCfm(transId(%ld))", measEvtCb->transId);
1901 RLOG1(L_DEBUG,"rlcUtlSndL2MeasCfm(transId(%d))", measEvtCb->transId);
1904 /* Clean up the RB data structures */
1905 measCb = &measEvtCb->measCb;
1907 cmMemset((U8*)&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
1908 measCfmEvt.transId = measEvtCb->transId;
1910 measCfmEvt.measType = measCb->measType;
1911 measCfmEvt.status.status = LCM_PRIM_OK;
1912 measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
1914 if(measCb->measType & LKW_L2MEAS_DL_IP)
1916 RlcL2MeasCbUeMeasInfo *pUeInfoLstCb = measCb->val.ipThMeas.ueInfoLst;
1917 RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
1919 for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)
1921 pUeInfoLstCfm[cfmIdx].numCfm = 0;
1922 if (pUeInfoLstCb[cntr].isValid == TRUE)
1924 pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
1925 pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
1926 for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
1928 qci = pUeInfoLstCb[cntr].qci[qciIdx];
1929 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
1931 dlDataVol = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation;
1932 dlTime = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation;
1934 if((0 == dlTime) || !(gCb->u.dlCb->rlcL2Cb.measOn[qci] & LKW_L2MEAS_DL_IP) )
1936 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 0;
1940 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut =
1941 (dlDataVol / dlTime);
1943 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut *= 8;
1945 /* Reset the values after reporting to Application */
1946 pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation = 0;
1947 pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation = 0;
1949 measCfmEvt.val.ipThMeas.ueInfoLst[cfmIdx].numCfm++;
1954 measCfmEvt.val.ipThMeas.numUes = cfmIdx;
1958 RlcL2Cntr *pMeasData = measCb->val.nonIpThMeas.measData;
1959 RlcL2MeasCfmNonIpThMeas *pMeasCfmNonIp = &measCfmEvt.val.nonIpThMeas;
1961 pMeasCfmNonIp->numCfm = 0;
1963 for(qciIdx = 0; qciIdx < LKW_MAX_QCI; qciIdx++)
1965 qci = measCb->val.nonIpThMeas.qci[qciIdx];
1968 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].qci = qci;
1970 if(measCb->measType & LKW_L2MEAS_UU_LOSS)
1972 dLoss = pMeasData[qci].uuLoss.dLoss;
1973 posPkts = pMeasData[qci].uuLoss.posPkts;
1974 if(((posPkts + dLoss) != 0))
1976 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.uuLoss =
1977 ((dLoss * 1000000) / (posPkts + dLoss));
1979 pMeasData[qci].uuLoss.dLoss = 0;
1980 pMeasData[qci].uuLoss.posPkts = 0;
1982 if(measCb->measType & LKW_L2MEAS_DL_DISC)
1985 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 0;
1986 if(pMeasData[qci].dlDisc.totSdus != 0)
1988 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate =
1989 (((pMeasData[qci].dlDisc.discSdus) * 1000000) / (pMeasData[qci].dlDisc.totSdus));
1992 pMeasData[qci].dlDisc.totSdus = 0;
1993 pMeasData[qci].dlDisc.discSdus = 0;
1995 if(measCb->measType & LKW_L2MEAS_DL_DELAY)
1997 if (pMeasData[qci].dlPjSduDelay.numSdus > 0)
1999 pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlSduDelay =
2000 (pMeasData[qci].dlPjSduDelay.sduDelay / pMeasData[qci].dlPjSduDelay.numSdus);
2001 pMeasData[qci].dlPjSduDelay.sduDelay = 0;
2002 pMeasData[qci].dlPjSduDelay.numSdus = 0;
2005 pMeasCfmNonIp->numCfm++;
2009 /* Fix Klock warning */
2010 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
2012 } /* rlcUtlSndL2MeasCfm */
2015 * @brief Handler for Sending Negative confirm .
2019 * This function is called when the l2 measurement cannot be started
2020 * This function sends negative confirm for all the requests
2022 * @param[in] measReqEvt Measurement Req Structure
2030 S16 rlcUtlSndDlL2MeasNCfm
2033 RlcL2MeasReqEvt *measReqEvt,
2034 RlcL2MeasCfmEvt *measCfmEvt
2037 S16 rlcUtlSndDlL2MeasNCfm(gCb,measReqEvt, measCfmEvt)
2039 RlcL2MeasReqEvt *measReqEvt;
2040 RlcL2MeasCfmEvt *measCfmEvt;
2043 TRC3(rlcUtlSndDlL2MeasNCfm)
2045 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
2047 } /* kwUtlSndL2MeasNCfm */
2050 * @brief Handler for resetting the RB data structures
2054 * This function resets the RB data structure after the expiry of
2055 * measurement timer.
2057 * @param[in] measCb Measurement Control Block.
2064 Void rlcUtlResetDlL2MeasInRlcRb
2067 RlcL2MeasCb *measCb,
2071 Void rlcUtlResetDlL2MeasInRlcRb(gCb, measCb, measType)
2073 RlcL2MeasCb *measCb;
2079 RlcDlUeCb *ueCb = NULL;
2083 if (measCb->measType & LKW_L2MEAS_DL_IP)
2085 for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
2087 if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
2089 for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
2091 if (measType & LKW_L2MEAS_DL_IP)
2093 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.volSummation = 0;
2094 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.timeSummation = 0;
2095 gCb->u.dlCb->rlcL2Cb.measOn[qciIdx] &= ~measType;
2099 if(ROK != rlcDbmFetchDlUeCb(gCb,measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
2100 measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
2110 /* for now the only meas should be DL discard in this case */
2111 if (measCb->measType & LKW_L2MEAS_DL_DISC)
2114 for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
2116 U8 qciVal = measCb->val.nonIpThMeas.qci[i];
2118 measCb->val.nonIpThMeas.measData[qciVal].dlDisc.discSdus = 0;
2119 measCb->val.nonIpThMeas.measData[qciVal].dlDisc.totSdus = 0;
2123 if (measCb->measType & LKW_L2MEAS_DL_DELAY)
2126 for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
2128 U8 qciVal = measCb->val.nonIpThMeas.qci[i];
2130 measCb->val.nonIpThMeas.measData[qciVal].dlPjSduDelay.sduDelay = 0;
2133 measCb->val.nonIpThMeas.numQci = 0;
2135 } /* rlcUtlResetDlL2MeasInRlcRb */
2138 PRIVATE Void dumpRLCDlRbInformation(RlcDlRbCb* dlRbCb)
2140 if(dlRbCb->mode == CM_LTE_MODE_UM)
2142 RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2143 "UM Downlink UEID:%d CELLID:%d Q size = %d",
2145 dlRbCb->rlcId.cellId,
2146 (int)dlRbCb->m.umDl.sduQ.count);
2148 else if(dlRbCb->mode == CM_LTE_MODE_AM)
2151 for(j = 0; j <= (RLC_AM_GET_WIN_SZ(dlRbCb->m.amDl.snLen)); j++)
2153 RlcTx *txBuf = rlcUtlGetTxBuf(dlRbCb->m.amDl.txBufLst, j);
2159 RLOG_ARG4(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2160 "AM Downlink UEID:%d CELLID:%d Sizes SDU Q = %d TX Q = %d ",
2162 dlRbCb->rlcId.cellId,
2163 (int)dlRbCb->m.amDl.sduQ.count,
2165 RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2166 "AM Downlink UEID:%d CELLID:%d RETX Q= %d",
2168 dlRbCb->rlcId.cellId,
2169 (int)dlRbCb->m.amDl.retxLst.count);
2173 Void DumpRLCDlDebugInformation(Void)
2175 RlcCb* dlInst = rlcCb[1]; /* TODO : Check whether DL is 0 or 1 */
2177 RlcDlCb *dlCb = dlInst->u.dlCb;
2179 RlcDlUeCb *ueCb = NULLP;
2180 RTLIN_DUMP_DEBUG("RLC Information\n");
2181 RTLIN_DUMP_DEBUG("===============\n");
2182 /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
2183 while (ROK == cmHashListGetNext(&dlCb->ueLstCp,
2188 for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
2190 RlcDlRbCb* dlRbCb = ueCb->srbCb[i];
2191 if( dlRbCb != NULLP)
2193 dumpRLCDlRbInformation(dlRbCb);
2196 for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
2198 RlcDlRbCb* dlRbCb = ueCb->drbCb[i];
2199 if( dlRbCb != NULLP)
2201 dumpRLCDlRbInformation(dlRbCb);
2206 RlcDlDataToBeFreed* pToBeFreed = &dlCb->toBeFreed;
2208 RTLIN_DUMP_DEBUG("toBeFreed RETX list size = %d\n",(int)pToBeFreed->reTxLst.count);
2209 RTLIN_DUMP_DEBUG("toBeFreed TX list size = %d\n",(int)pToBeFreed->txLst.count);
2210 RTLIN_DUMP_DEBUG("toBeFreed SDU list size = %d\n",(int)pToBeFreed->sduLst.count);
2211 RTLIN_DUMP_DEBUG("toBeFreed RB list size = %d\n",(int)pToBeFreed->rbLst.count);
2217 * This function frees downlink memory
2226 void rlcUtlFreeDlMem
2231 void rlcUtlFreeDlMem()
2235 rlcUtlFreeDlMemory(RLC_GET_RLCCB(RLC_DL_INST));
2241 * This function returns current time
2250 void rlcUtlGetCurrTime
2255 void rlcUtlGetCurrTime(U32 *currTime)
2259 TRC2(rlcUtlGetCurrTime)
2261 /* Need t define else part for PAL */
2262 *currTime = SGetTtiCount();
2265 #if defined(MAC_RLC_HARQ_STA_RBUF) || defined (SS_RBUF)
2268 void rlcUtlDlBatchProcHqStaInd
2273 void rlcUtlDlBatchProcHqStaInd()
2277 /* Read from Ring Buffer and process PDCP packets */
2280 Void *elmIndx = NULLP;
2281 RguHarqStaInd *staInd = NULLP;
2283 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2284 isDatReqProcessed = TRUE;
2286 elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ);
2287 while(NULLP != elmIndx)
2289 staInd = (RguHarqStaInd *)elmIndx;
2290 RlcLiRguHqStaInd(&(staInd->pst), 0, &(staInd->hqStatusInd));
2294 SRngIncrRIndx(SS_RNG_BUF_MAC_HARQ);
2296 if((elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ)) == NULLP)
2298 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2299 isDatReqProcessed = FALSE;
2309 * @brief evaluate and trigger PDB based flow control to PDCP
2313 * @param[in] rbCb RB control block
2320 Void rlcUtlTrigPdbFlowCntrl
2327 Void rlcUtlTrigPdbFlowCntrl(gCb,rbCb,pktAdmitCnt)
2333 KwuFlowCntrlIndInfo *flowCntrlInfo;
2334 RlcKwuSapCb* rlckwuSap;
2336 rlckwuSap = gCb->u.dlCb->rlcKwuDlSap + RLC_UI_PDCP;
2338 RLC_SHRABL_STATIC_BUF_ALLOC(rlckwuSap->pst.region,
2339 rlckwuSap->pst.pool,
2341 sizeof(KwuFlowCntrlIndInfo));
2342 flowCntrlInfo->rlcId = rbCb->rlcId;
2343 flowCntrlInfo->pktAdmitCnt = pktAdmitCnt;
2344 RlcUiKwuFlowCntrlInd(&rlckwuSap->pst, rlckwuSap->suId, flowCntrlInfo);
2349 * @brief Store the DL buffer in hashList
2354 * Use the SN % binSize as key and store the received UL buffer
2355 * @param[in] txBufLst List CP array
2356 * @param[in] txBuf transmitted buffer
2357 * @param[in] sn sn of the received buffer
2363 Void rlcUtlStoreTxBuf
2365 CmLListCp *txBufLst,
2370 Void rlcUtlStoreTxBuf(txBufLst, txBuf, sn)
2371 CmLListCp *txBufLst;
2378 TRC3(kwUtlStoretxBuf)
2379 //printf("S-sn(%d)\n", sn);
2380 hashKey = (sn % RLC_TX_BUF_BIN_SIZE );
2382 txBuf->lnk.node = (PTR)txBuf;
2383 cmLListAdd2Tail(&(txBufLst[hashKey]), &txBuf->lnk);
2386 } /* rlcUtlStoreRecBuf */
2390 * @brief Retrieve the DL buffer from the list
2395 * Use the SN % binSize as key and retrieve the DL buffer
2396 * @param[in] txBufLst List CP array
2397 * @param[in] sn sn of the transmitted buffer
2403 RlcTx* rlcUtlGetTxBuf
2405 CmLListCp *txBufLst,
2409 RlcTx* rlcUtlGetTxBuf(txBufLst, sn)
2410 CmLListCp *txBufLst;
2415 CmLListCp *txBufLstCp;
2417 CmLList *node = NULLP;
2419 TRC3(rlcUtlGetTxBuf)
2420 //printf("G-sn(%d)\n", sn);
2422 hashKey = (sn % RLC_TX_BUF_BIN_SIZE );
2424 txBufLstCp = &txBufLst[hashKey];
2425 CM_LLIST_FIRST_NODE(txBufLstCp, node);
2428 txBuf = (RlcTx *) node->node;
2433 CM_LLIST_NEXT_NODE(txBufLstCp, node);
2436 } /* rlcUtlStoreTxBuf */
2439 * @brief Delete the DL buffer from the list
2444 * Use the SN % binSize as key and retrieve the DL buffer
2445 * @param[in] txBufLst List CP array
2446 * @param[in] sn sn of the transmitted bffer
2454 CmLListCp *txBufLst,
2459 Void rlcUtlDelTxBuf(txBufLst, txBuf, gCb)
2460 CmLListCp *txBufLst;
2466 CmLListCp *txBufLstCp;
2468 TRC3(rlcUtlDelTxBuf)
2470 hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE );
2472 txBufLstCp = &txBufLst[hashKey];
2473 //printf("D-sn(%d)\n", txBuf->hdr.sn);
2474 cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2475 RLC_FREE_WC(gCb, txBuf, sizeof(RlcTx));
2477 } /* rlcUtlDelTxBuf */
2481 * @brief Remove the DL buffer from the list
2486 * Use the SN % binSize as key and retrieve the DL buffer
2487 * @param[in] txBufLst List CP array
2488 * @param[in] sn sn of the transmitted bffer
2494 Void rlcUtlRemovTxBuf
2496 CmLListCp *txBufLst,
2501 Void rlcUtlRemovTxBuf(txBufLst, txBuf, gCb)
2502 CmLListCp *txBufLst;
2508 CmLListCp *txBufLstCp;
2510 TRC3(rlcUtlRemovTxBuf)
2512 hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE );
2514 txBufLstCp = &txBufLst[hashKey];
2515 //printf("D-sn(%d)\n", txBuf->hdr.sn);
2516 cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2518 } /* rlcUtlRemovTxBuf */
2522 /********************************************************************30**
2524 **********************************************************************/