Moving all common header file into common_def.h file
[o-du/l2.git] / src / 5gnrrlc / kw_utl_dl.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /**********************************************************************
20
21      Name:     LTE-RLC Layer 
22   
23      Type:     C file
24   
25      Desc:     Source code for RLC Utility Module
26                This file contains following functions
27
28                   --kwUtlSndToLi
29                   --kwUtlRcvFrmLi
30                   --kwUtlEmptySduQ
31                   --kwUtlSndDStaRsp
32                   --kwUtlSndDatInd 
33                   --kwUtlShutDown
34
35      File:     kw_utl_dl.c
36
37 **********************************************************************/
38 static const char* RLOG_MODULE_NAME="UTL";
39 static int RLOG_MODULE_ID=2048;
40 static int RLOG_FILE_ID=209;
41
42 /** @file kw_utl_dl.c
43 @brief RLC Utility Module 
44 */
45
46 /* header (.h) include files */
47
48 #include "common_def.h"
49 /* kw005.201 added support for L2 Measurement */
50 #ifdef LTE_L2_MEAS
51 #include <sys/time.h>
52 #endif
53 #include "ckw.h"           /* CKW defines */
54 #include "kwu.h"           /* CKW defines */
55 #include "lkw.h"           /* LKW defines */
56 #include "rgu.h"           /* RGU defiens */
57
58 #include "kw_env.h"        /* RLC environment options */
59 #include "kw.h"            /* RLC defines */
60 #include "kw_err.h"        /* Error defines */
61 #include "kw_udx.h"
62 #include "kw_dl.h"
63
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 */
69
70 #include "kw.x"            /* RLC includes */
71 #include "kw_udx.x"        /* UDX interface includes */
72 #include "kw_dl.x"         /* RLC downlink includes */
73
74 #include "ss_rbuf.h"
75 #include "ss_rbuf.x" 
76
77 EXTERN SsRngBufCnt rngCb;
78
79 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS))
80 extern U32 isDatReqProcessed;
81 #endif
82 #define KW_MODULE (KW_DBGMASK_DUT | KW_DBGMASK_DL) /* for debugging purpose */
83 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)) || defined (SS_RBUF)
84 EXTERN void kwUtlDlBatchProcHqStaInd ARGS ((Void));
85 #endif
86 Void ResetRLCStats(Void)
87 {
88    KwCb* dlInst = kwCb[1]; 
89    KwCb* ulInst = kwCb[0]; 
90    cmMemset((U8*)&gRlcStats, 0, sizeof(RLCStats));
91    cmMemset((U8*)&dlInst->genSts,0,sizeof(KwGenSts));
92    cmMemset((U8*)&ulInst->genSts,0,sizeof(KwGenSts));
93 }
94
95 #ifndef ALIGN_64BIT
96 Void PrintRLCStats(Void)
97 {
98    KwCb* dlInst = kwCb[1]; 
99    KwCb* ulInst = kwCb[0]; 
100
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);
122
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);
139 }
140 #else
141 Void PrintRLCStats(Void)
142 {
143    KwCb* dlInst = kwCb[1]; 
144    KwCb* ulInst = kwCb[0]; 
145
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);
175 */
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"
187
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);
199 }
200 #endif
201
202 /*******************************************************************
203  *
204  * @brief 
205  *    Handler for storing all DL PDU Info into RLC-MAC interface
206  *    struct and sending to lower interface
207  *
208  * @details
209  *    This function stores DL PDU info for all logical channels
210  *    of per UE grant per TTI and sends to MAC
211  *
212  *    Function : KwLiRguDDatReq 
213  *
214  * @params[in] 
215  * @return ROK     - success
216  *         RFAILED - failure
217  *
218  * ****************************************************************/
219 #ifdef ANSI
220 PUBLIC S16 KwLiRguDDatReq
221 (
222 Pst               *post,
223 SpId              spId,
224 RguDDatReqInfo    *datReqInfo
225 )
226 #else
227 PUBLIC S16 KwLiRguDDatReq(post, spId, datReqInfo)
228 Pst               *post;
229 SpId              spId;
230 RguDDatReqInfo    *datReqInfo;
231 #endif
232 {
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 */
241
242    TRC3(KwLiRguDDatReq)
243
244    dlData = NULLP;
245    KW_ALLOC_SHRABL_BUF(post->region, post->pool,
246                        dlData, sizeof(RlcMacData));
247 #if (ERRCLASS & ERRCLS_ADD_RES)
248    if ( datReqInfo == NULLP )
249    {
250       RLOG0(L_FATAL,"Memory allocation failed");
251       RETVALUE(RFAILED);
252    }
253 #endif /* ERRCLASS & ERRCLS_ADD_RES */
254
255    for(ueIdx = 0; ueIdx < datReqInfo->nmbOfUeGrantPerTti; ueIdx++)
256    {
257       datPerUe = datReqInfo->datReq[ueIdx];
258
259       cmMemset((U8 *)dlData, 0, sizeof(RlcMacData));
260
261       dlData->cellId = datReqInfo->cellId;
262       dlData->rnti = datPerUe.rnti;
263       //dlData->timeToTx = datPerUe.transId; /* Derive timing info from transId */
264       dlData->nmbPdu = 0;
265
266       for(tbIdx = 0; tbIdx < datPerUe.nmbOfTbs; tbIdx++)
267       {
268          datPerTb = datPerUe.datReqTb[tbIdx];
269          for(lchIdx = 0; lchIdx < datPerTb.nmbLch; lchIdx++)
270          {
271             datPerLch = datPerTb.lchData[lchIdx];
272             for(pduIdx = 0; pduIdx < datPerLch.pdu.numPdu; pduIdx++)
273             {
274                dlData->pduInfo[dlData->nmbPdu].commCh = FALSE;
275                dlData->pduInfo[dlData->nmbPdu].lcId = datPerLch.lcId;
276                dlData->pduInfo[dlData->nmbPdu].pduBuf = datPerLch.pdu.mBuf[pduIdx];
277                dlData->nmbPdu++;
278             }/* For per PDU */
279          }/* For Data per Lch */
280       }/* For Data per Tb */
281       RlcMacSendDlData(post, spId, dlData);
282    } /* For Data per UE */
283
284    /* Check if to be freed here */
285    
286    KW_FREE_SHRABL_BUF(post->region, 
287             post->pool, 
288             datReqInfo, sizeof(RguDDatReqInfo));
289    
290    RETVALUE(ROK);
291 }/* End of KwLiRguDDatReq */
292
293 /**
294  *
295  * @brief 
296  *        Handler for sending the data to multiple logical channels of a UE
297  *
298  * @details:
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
302  *        by MAC. 
303  *
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  
307  *
308  * @return  S16
309  *      -# ROK 
310  *      -# RFAILED
311  *
312  */
313 #ifdef ANSI
314 PUBLIC S16 kwUtlSndToLi
315 (
316 KwCb            *gCb,
317 SuId            suId,
318 KwDStaIndInfo   *staIndInfo
319 )
320 #else
321 PUBLIC S16 kwUtlSndToLi(gCb, suId, staIndInfo)
322 KwCb            *gCb;
323 SuId            suId;
324 KwDStaIndInfo   *staIndInfo; 
325 #endif
326 {
327    KwDlUeCb         *ueCb;         /* UE control block */
328    U32              count;         /* Loop Counter */
329    U32              numTb;         /* Number of Tbs */
330    KwDlRbCb         *rbCb;         /* RB Control Block */
331    KwDatReq         datReq;        /* PDUs Information */
332    RguDDatReqInfo   *datReqInfo;   /* Data Request Information */
333    KwRguSapCb       *rguSap;       /* MAC SAP CB */
334    U32              totNumPdu;     /* Total number of PDUS */
335    RguStaIndTb      *staIndTb = NULLP;
336    RguDatReqTb      *datReqTb = NULLP;
337    RguDStaIndPerUe  *staInd = NULLP;
338 #ifdef LTE_L2_MEAS   
339     U32 grantPerLch[RGU_MAX_LC] = {0};
340 #endif
341 /* kw005.201 added support for L2 Measurement */
342 #ifdef LTE_L2_MEAS_LOSS_DELAY
343    U8        snIdx1;
344    U8        snIdx2;
345 #endif /* LTE_L2_MEAS */
346    U32 idx;
347
348 //Debug
349    U32 staIndSz=0,datIndSz = 0;
350    TRC2(kwUtlSndToLi)
351
352
353    datReqInfo = NULLP;
354    KW_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 )
359       {
360          RLOG_ARG0(L_FATAL,DBG_CELLID,staIndInfo->cellId,
361                   "Memory allocation failed");
362          RETVALUE(RFAILED);
363       }
364 #endif /* ERRCLASS & ERRCLS_ADD_RES */
365    for(idx = 0; idx < staIndInfo->nmbOfUeGrantPerTti; idx++)
366    {
367       staInd = &staIndInfo->staInd[idx];
368       /* Fetch Ue control block */
369       if(ROK != kwDbmFetchDlUeCb(gCb,staInd->rnti,staIndInfo->cellId,&ueCb))
370       {
371          /* Fetch UeCb failed */
372          RLOG_ARG1(L_ERROR, DBG_CELLID,staIndInfo->cellId, 
373                   "UeId[%u]:ueCb not found",
374                   staInd->rnti);
375          /* If ueCb is not found for current rnti then continue to look for next rnti*/
376          continue; 
377       }
378       /* kw002.201 Removed the allocation of KwDatReq */
379       /* kw004.201 Used SSI function to initialize the variable */
380       cmMemset( (U8 *)&datReq, 0, sizeof(KwDatReq) ); 
381       totNumPdu = 0;
382       for (numTb = 0; numTb < staInd->nmbOfTbs; numTb++)
383       {
384          staIndTb = &(staInd->staIndTb[numTb]);
385          datReqTb = &(datReqInfo->datReq[idx].datReqTb[numTb]);
386 #ifdef LTE_L2_MEAS
387          ueCb->tbIdx = (ueCb->tbIdx+1) % KW_MAX_TB_PER_UE;
388 #endif   
389          for (count = 0;count < staIndTb->nmbLch; count++)
390          {
391 #ifdef LTE_L2_MEAS
392             /*Calculate the total grant size from MAC */
393             if((staIndTb->lchStaInd[count].lcId >= RGU_MAX_LC) 
394                 || (staIndTb->lchStaInd[count].lcId == 0))
395             {
396                /* TODO : Need to figure out why this is happening */
397                break;
398             }
399             else
400             {
401                grantPerLch[staIndTb->lchStaInd[count].lcId] += staIndTb->lchStaInd[count].totBufSize;
402             }
403 #endif   
404             rbCb = ueCb->lCh[staIndTb->lchStaInd[count].lcId - 1].dlRbCb;
405
406             if (rbCb && (!kwDlUtlIsReestInProgress(rbCb)))
407             { 
408 //Debug
409                staIndSz += staIndTb->lchStaInd[count].totBufSize;
410                datReq.pduSz = staIndTb->lchStaInd[count].totBufSize;
411 #ifdef LTE_L2_MEAS            
412                datReq.totMacGrant = grantPerLch[staIndTb->lchStaInd[count].lcId];
413 #endif
414                kwUtlGetCurrTime(&datReq.boRep.oldestSduArrTime);
415                if ( CM_LTE_MODE_UM == rbCb->mode )
416                {
417                   kwUmmProcessSdus(gCb,rbCb,&datReq);
418                }
419                else if ( CM_LTE_MODE_AM == rbCb->mode )
420                {
421                   kwAmmProcessSdus(gCb,rbCb,&datReq,staInd->fillCtrlPdu);
422                }
423 #ifdef LTE_L2_MEAS            
424                grantPerLch[staIndTb->lchStaInd[count].lcId] = datReq.totMacGrant;
425 #endif
426                if ( 0 == datReq.pduInfo.numPdu )
427                {
428                   continue;
429                }
430                totNumPdu += datReq.pduInfo.numPdu;
431                cmMemcpy((U8 *)(&(datReqTb->lchData[count].pdu)),
432                      (U8 *)(&(datReq.pduInfo)),sizeof(KwPduInfo));
433
434 //Debug
435                U8 numPdu = 0;
436                for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
437                {
438                   MsgLen len = 0;
439                   SFndLenMsg(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
440                   datIndSz += len; 
441                }
442                datReqTb->lchData[count].setMaxUlPrio = FALSE;
443                if (KW_AM_IS_POLL_BIT_SET(AMDL) && 
444                    (AMDL.sduQ.count > 1))
445                { 
446                   /* Poll bit is set indicate to MAC*/
447                   datReqTb->lchData[count].setMaxUlPrio = TRUE;
448                }
449                datReqTb->lchData[count].boReport.bo = datReq.boRep.bo;
450
451 #ifdef CCPU_OPT
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;
460
461 #ifdef L2_OPTMZ
462                /* Set if Bearer is UM */
463                if ( CM_LTE_MODE_UM == rbCb->mode )
464                {
465                   datReqTb->lchData[count].freeBuff = TRUE;
466                }
467                else
468                {
469                   datReqTb->lchData[count].freeBuff = FALSE;
470                }
471 #endif
472
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 
479                 */
480                for(snIdx1 = 0; snIdx1 < RGU_MAX_PDU; snIdx1++)
481                {
482                   datReqTb->rguSnInfo->lchMap[count].snList[snIdx1] = 0xffff;
483                }
484                if(tbSnMap->numSn != 0)
485                {
486                   snIdx2 = 0;
487                   for(snIdx1=tbSnMap->prevNumSn;snIdx1 < tbSnMap->numSn;snIdx1++)
488                   {
489                      datReqTb->rguSnInfo->lchMap[count].snList[snIdx2++] = 
490                         tbSnMap->snSduMap[snIdx1].sn;
491                   }
492                   tbSnMap->prevNumSn = tbSnMap->numSn;
493                }
494 #endif
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(KwDatReq) ); 
499             }
500          }
501 #ifdef LTE_L2_MEAS
502          if(ueCb->l2MeasTbCb[ueCb->tbIdx]!= NULLP)
503          {
504             datReqTb->tbId = ueCb->tbIdx;
505          }
506          else
507          {
508             datReqTb->tbId = KW_INVALID_TBID; 
509          }
510 #endif
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 )
515          {
516             datReqTb->lchData[0].lcId = staIndTb->lchStaInd[0].lcId;
517          }
518          /* kw005.201 added support for L2 Measurement */
519 #ifdef LTE_L2_MEAS_LOSS_DELAY
520          if(tbSnMap->numSn == 0)
521          {
522             KW_FREE(tbSnMap,sizeof(KwTbSnMap));
523             KW_FREE(datReqTb->rguSnInfo,sizeof(RguSnMapInfo));
524             datReqTb->rguSnInfo = NULLP;
525             kwCb.kwL2Cb.curTbSnMap = NULLP;
526             datReqTb->snMapPres = FALSE;
527          }
528          else
529          {
530             cmHashListInsert(&(kwCb.kwL2Cb.tbHlCp),(PTR)tbSnMap,
531                   (U8 *) &(tbSnMap->tbId), (U16)sizeof(tbSnMap->tbId));
532             kwCb.kwL2Cb.curTbSnMap = NULLP;
533          }
534 #endif /* LTE_L2_MEAS */
535       }
536       datReqInfo->datReq[idx].nmbOfTbs = staInd->nmbOfTbs;
537       datReqInfo->datReq[idx].transId = staInd->transId;
538       datReqInfo->datReq[idx].rnti    = staInd->rnti;
539    }
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 )
544    {
545       /* Populate the trace params */
546       kwLmmSendTrc(gCb,EVTRGUDDATREQ, NULLP);
547    }
548
549    rguSap = &(gCb->u.dlCb->rguDlSap[suId]);
550 //Debug
551    KwLiRguDDatReq(&rguSap->pst,rguSap->spId,datReqInfo); 
552    RETVALUE(ROK);
553 }
554
555 /**
556  *
557  * @brief 
558  *        Handler for sending Status Response to MAC. 
559  *
560  * @detail:
561  *        This function is used by  RLC entity for sending
562  *        status response to MAC after receiving a SDU from
563  *        PDCP.
564  *
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
570  *
571  * @return  S16
572  *      -# ROK 
573  *      -# RFAILED
574  */
575 #ifdef ANSI
576 PUBLIC S16 kwUtlSndDStaRsp
577 (
578 KwCb       *gCb,
579 KwDlRbCb   *rbCb,     
580 S32        bo,        
581 S32        estHdrSz,  
582 Bool       staPduPrsnt,
583 U32        staPduBo
584 )
585 #else
586 PUBLIC S16 kwUtlSndDStaRsp(gCb,rbCb,bo,estHdrSz,staPduPrsnt,staPduBo)
587 KwCb       *gCb;
588 KwDlRbCb   *rbCb;      
589 S32        bo;         
590 S32        estHdrSz;   
591 Bool       staPduPrsnt;
592 U32        staPduBo;
593 #endif
594 {
595    RlcMacBOStatus   boStatus;      /* Buffer occupancy status information */
596    KwRguSapCb       *rguSap;       /* MAC SAP Information */
597    TRC3(kwUtlSndDStaRsp)
598 #ifndef TENB_ACC
599    if ((rbCb->lastRprtdBoToMac > (U32)8000) && (rbCb->boUnRprtdCnt < (U32)5) 
600        && (!staPduPrsnt) && ((CM_LTE_MODE_AM == rbCb->mode ) && (AMDL.nxtRetx == NULLP)))
601    {
602       rbCb->boUnRprtdCnt++;
603       RETVALUE(ROK);
604    }
605 #endif
606
607    rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]);
608
609    rbCb->boUnRprtdCnt = (U32)0;
610    rbCb->lastRprtdBoToMac = (U32)bo;
611
612    boStatus.cellId = rbCb->rlcId.cellId;
613    boStatus.rnti = rbCb->rlcId.ueId;
614    boStatus.commCh = FALSE; 
615    boStatus.lcId = rbCb->lch.lChId;
616    boStatus.bo = bo;
617
618    /* If trace flag is enabled send the trace indication */
619    if(gCb->init.trc == TRUE)
620    {
621       /* Populate the trace params */
622       kwLmmSendTrc(gCb, EVTRLCBOSTA, NULLP);
623    }
624    /* Send Status Response to MAC layer */
625    RlcMacSendBOStatus(&rguSap->pst,rguSap->spId,&boStatus);
626
627
628    RETVALUE(ROK);
629 }
630
631 /**
632  *
633  * @brief 
634  *        Handler for emptying the SDU queue. 
635  * 
636  * @detail:
637  *        This function is used to empty the SDU queue when
638  *        a re-establishment request is received from the 
639  *        upper layer.
640  *
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
644  *
645  * @return Void 
646  */
647 /* kw005.201 added support for L2 Measurement */
648 #ifdef LTE_L2_MEAS_RLC
649 #ifdef ANSI
650 PUBLIC Void kwUtlEmptySduQ
651 (
652 KwCb        *gCb, 
653 KwDlRbCb    *rbCb,
654 CmLListCp   *sduQ 
655 )
656 #else
657 PUBLIC Void kwUtlEmptySduQ(gCb,rbCb, sduQ)
658 KwCb        *gCb;
659 KwDlRbCb    *rbCb;
660 CmLListCp   *sduQ;
661 #endif
662 #else
663 #ifdef ANSI
664 PUBLIC Void kwUtlEmptySduQ
665 (
666 KwCb        *gCb,
667 CmLListCp   *sduQ 
668 )
669 #else
670 PUBLIC Void kwUtlEmptySduQ(gCb,sduQ)
671 KwCb        *gCb;
672 CmLListCp   *sduQ; 
673 #endif
674 #endif
675 {
676 #ifdef LTE_L2_MEAS_RLC
677    CmLListCp   *sduSnMapQ;             /* SDU Sequence number map queue */
678    CmLList     *firstSduSnMap;         /* First Node in SDU SnMap Queue */
679    KwSduSnMap  *sduSnMap;              /* SDU Sn Map */
680
681    TRC2(kwUtlEmptySduQ)
682    sduSnMapQ = NULLP;
683    firstSduSnMap = NULLP;
684    sduSnMap = NULLP;
685
686
687    sduSnMapQ = &rbCb->sduSnMapQ;
688    CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
689
690    while(firstSduSnMap)
691    {
692       sduSnMap = (KwSduSnMap *)firstSduSnMap->node;
693       if(sduSnMap != NULLP)
694       {
695          cmLListDelFrm(&(rbCb->sduSnMapQ), &(sduSnMap->lstEnt));
696          KW_FREE(sduSnMap, sizeof(KwSduSnMap));
697          CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
698       }
699       else
700       {
701          CM_LLIST_NEXT_NODE(sduSnMapQ, firstSduSnMap);
702       }
703    }
704 #endif
705    RETVOID;
706 }
707
708 /**
709  *
710  * @brief 
711  *    Handler for calculating the Length Indicator (LI) length for a SDU 
712  * 
713  * @detail:
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.
717  *
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
722  *
723  * @return  void 
724  */
725 #ifdef ANSI
726 PUBLIC Void kwUtlCalcLiForSdu
727 (
728 KwCb     *gCb,
729 U16      numLi, 
730 MsgLen   msgLen,
731 S16      *pduSz 
732 )
733 #else
734 PUBLIC Void kwUtlCalcLiForSdu(gCb,numLi,msgLen,pduSz)
735 KwCb     *gCb;
736 U16      numLi; 
737 MsgLen   msgLen;
738 S16      *pduSz;
739 #endif 
740 {
741    TRC2(kwUtlCalcLiForSdu)
742
743    if ( (*pduSz > msgLen)  && (msgLen < KW_2K_BYTE))
744    {
745       if(0 == (numLi & KW_BIT0)) /* check if number of LIs are odd or even */
746       {  
747          /* if number of LI's are even 2 bytes needed */
748          *pduSz -= 2;
749       }
750       else
751       {
752          /* if number of LI's are odd one byte needed */
753          *pduSz -= 1;
754       }
755    }
756    RETVOID;
757 }
758
759 /**
760  *
761  * @brief 
762  *    Function to set that re-establishment has started for an RB
763  * 
764  * @detail:
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;
769  *    it is stopped
770  *
771  * @param[in]      gCb      RLC instance control block 
772  * @param[in]      rbCb     RB for which re-establishment has started 
773  *
774  * @return  void 
775  */
776 #ifdef ANSI
777 PUBLIC Void kwDlUtlSetReestInProgressForRB
778 (
779 KwCb     *gCb,
780 KwDlRbCb *rbCb
781 )
782 #else
783 PUBLIC Void kwDlUtlSetReestInProgressForRB(gCb,rbCb)
784 KwCb     *gCb;
785 KwDlRbCb *rbCb;
786 #endif 
787 {
788    TRC2(kwDlUtlSetReestInProgressForRB)
789       
790    rbCb->reestInProgress = TRUE;
791    
792    if(rbCb->mode == CM_LTE_MODE_AM )
793    {
794       rbCb->m.amDl.estHdrSz = 0;
795
796       if(kwChkTmr(gCb, (PTR)rbCb, KW_EVT_AMDL_POLL_RETX_TMR))
797       {
798          kwStopTmr(gCb, (PTR)rbCb, KW_EVT_AMDL_POLL_RETX_TMR);
799       }
800    }
801    else
802    {
803       rbCb->m.umDl.estHdrSz= 0;
804    }
805
806    kwUtlSndDStaRsp(gCb, rbCb, 0, 0, FALSE,0);
807
808    RETVOID;
809 }
810
811 /**
812  *
813  * @brief 
814  *    Function to check if re-establishment is ongoing for an RB
815  * 
816  * @param[in]      rbCb     RB for which re-establishment is to be checked 
817  *
818  * @return  Bool
819  *          TRUE  : Re-establishment is in progress
820  *          FALSE : Re-establishment is not in progress
821  */
822 #ifdef ANSI
823 PUBLIC Bool kwDlUtlIsReestInProgress
824 (
825 KwDlRbCb *rbCb
826 )
827 #else
828 PUBLIC Bool kwDlUtlIsReestInProgress(rbCb)
829 KwDlRbCb *rbCb;
830 #endif 
831 {
832    TRC2(kwDlUtlSetReestInProgressForRB)
833
834    RETVALUE(rbCb->reestInProgress);
835 }
836
837 /**
838  *
839  * @brief 
840  *    Function to set re-establishment to FALSE
841  * 
842  * @param[in]      rbCb     RB for which re-establishment is to be reset 
843  *
844  * @return  Void
845  */
846 #ifdef ANSI
847 PUBLIC Void kwDlUtlResetReestInProgress
848 (
849 KwDlRbCb *rbCb
850 )
851 #else
852 PUBLIC Void kwDlUtlResetReestInProgress(rbCb)
853 KwDlRbCb *rbCb;
854 #endif 
855 {
856    TRC2(kwDlUtlSetReestInProgressForRB)
857
858    rbCb->reestInProgress = FALSE;
859 }
860
861 /**
862  *
863  * @brief 
864  *    Function to set that re-establishment has started for all the RBs
865  *    of an UE; except for SRB1
866  *
867  * @detail: For SRB1 only the poll-retransmit timer is stopped
868  * 
869  * @param[in]      gCb      RLC instance control block 
870  * @param[in]      ueCb     UE for which re-establishment has started 
871  *
872  * @return  void 
873  */
874 #ifdef ANSI
875 PUBLIC Void kwDlUtlSetReestInProgressForAllRBs
876 (
877 KwCb     *gCb,
878 KwDlUeCb *ueCb
879 )
880 #else
881 PUBLIC Void kwDlUtlSetReestInProgressForAllRBs(gCb,ueCb)
882 KwCb     *gCb;
883 KwDlUeCb *ueCb;
884 #endif 
885 {
886    U32        rbIdx;
887    
888    TRC2(kwDlUtlSetReestInProgressForAllRBs)
889
890    for(rbIdx = 0;rbIdx < KW_MAX_SRB_PER_UE;rbIdx++)
891    {
892       if(ueCb->srbCb[rbIdx] != NULLP)
893       {
894          if(ueCb->srbCb[rbIdx]->rlcId.rbId != 1)
895          {
896             kwDlUtlSetReestInProgressForRB(gCb,ueCb->srbCb[rbIdx]); 
897          }
898          else
899          {
900             /* For SRB we just need to stop the poll re-transmit timer */
901             if(kwChkTmr(gCb, (PTR)ueCb->srbCb[rbIdx], KW_EVT_AMDL_POLL_RETX_TMR))
902             {
903                kwStopTmr(gCb, (PTR)ueCb->srbCb[rbIdx], KW_EVT_AMDL_POLL_RETX_TMR);
904             }
905          }
906       }
907    }
908    
909    for(rbIdx = 0;rbIdx < KW_MAX_DRB_PER_UE;rbIdx++)
910    {
911       if(ueCb->drbCb[rbIdx] != NULLP)
912       {
913          kwDlUtlSetReestInProgressForRB(gCb,ueCb->drbCb[rbIdx]);
914       }
915    }
916       
917    RETVOID;
918 }
919
920 /**
921  * @brief  Function to increment number of SDUs transmitted 
922  *         in KWU SAP statistics
923  *
924  *
925  * @param[in]  kwuSap     KWU SAP in which to increment the counter
926  *
927  * @return  Void
928  */
929 #ifdef ANSI
930 PUBLIC Void kwUtlIncrementKwuStsSduTx
931 (
932 KwKwuSapCb *kwuSap 
933 )
934 #else
935 PUBLIC Void kwUtlIncrementKwuStsSduTx(kwuSap)
936 KwKwuSapCb *kwuSap;
937 #endif
938 {
939    kwuSap->sts.sduTx++;
940    RETVOID;
941 }
942
943 /**
944  * @brief  Function to increment number of bytes and PDUs transmitted 
945  *         in General statistics
946  *
947  *
948  * @param[in]  genSts   KWU SAP in which to increment the counter
949  * @param[in]  pdu      The PDU which is sent
950  *
951  * @return  Void
952  */
953 #ifdef ANSI
954 PUBLIC Void kwUtlIncrementGenStsBytesAndPdusSent
955 (
956 KwGenSts   *genSts,
957 Buffer     *pdu   
958 )
959 #else
960 PUBLIC Void kwUtlIncrementGenStsBytesAndPdusSent(genSts, pdu)
961 KwGenSts   *genSts;
962 Buffer     *pdu; 
963 #endif
964 {
965    MsgLen bytesSent;
966    SFndLenMsg(pdu, &bytesSent);
967    genSts->bytesSent += bytesSent;
968    genSts->pdusSent++;
969    RETVOID;
970 }
971
972 /**
973  * @brief  Function to initialize the data structures used to free memory
974  *
975  *
976  * @param[in]  gCb        RLC instance control block
977  * @param[out] toBeFreed  Pointer to the freeing structure. This is 
978  *                        initialized here
979  *
980  * @return  Void
981  */
982 #ifdef ANSI
983 PUBLIC Void kwUtlInitToBeFreed
984 (
985 KwCb                *gCb,
986 KwDlDataToBeFreed   *toBeFreed
987 )
988 #else
989 PUBLIC Void kwUtlInitToBeFreed(gCb, toBeFreed)
990 KwCb                *gCb;
991 KwDlDataToBeFreed   *toBeFreed;
992 #endif
993 {
994    cmLListInit(&(toBeFreed->sduLst));
995    cmLListInit(&(toBeFreed->rbLst));
996    cmLListInit(&(toBeFreed->reTxLst));
997    cmLListInit(&(toBeFreed->txLst));
998    
999    RETVOID;
1000 }
1001
1002 /**
1003  * @brief  Function to initialize the DL self Pst structure
1004  *
1005  *
1006  * @param[in]  gCb   RLC instance control block
1007  *
1008  * @return  Void
1009  */
1010 #ifdef ANSI
1011 PUBLIC Void kwUtlInitializeSelfPst
1012 (
1013 KwCb *gCb  
1014 )
1015 #else
1016 PUBLIC Void kwUtlInitializeSelfPst(gCb)
1017 KwCb *gCb;
1018 #endif
1019 {
1020    Pst *selfPst = &gCb->u.dlCb->selfPst;
1021    
1022    KW_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;
1031 }
1032
1033 /**
1034  * @brief  Function to send a DL cleanup event
1035  *
1036  *
1037  * @param[in]  gCb   RLC instance control block
1038  *
1039  * @return  Void
1040  */
1041 #ifdef ANSI
1042 PUBLIC Void kwUtlRaiseDlCleanupEvent
1043 (
1044 KwCb *gCb  
1045 )
1046 #else
1047 PUBLIC Void kwUtlRaiseDlCleanupEvent(gCb)
1048 KwCb *gCb;
1049 #endif
1050 {
1051 #ifdef KWSELFPSTDLCLEAN
1052    if(!gCb->u.dlCb->eventInQueue)
1053    {
1054       SPstTsk(&gCb->u.dlCb->selfPst, gCb->u.dlCb->selfPstMBuf);
1055       gCb->u.dlCb->eventInQueue = TRUE;
1056    }
1057 #endif
1058    RETVOID;
1059 }
1060
1061 /**
1062  * @brief  Function to add a SDU to the to be freed sdu list
1063  *
1064  *
1065  * @param[in]  gCb   RLC instance control block
1066  * @param[in]  sdu   SDU to be added to the list
1067  *
1068  * @return  Void
1069  */
1070 #ifdef ANSI
1071 PUBLIC Void kwUtlAddSduToBeFreedQueue
1072 (
1073 KwCb    *gCb,
1074 KwSdu   *sdu
1075 )
1076 #else
1077 PUBLIC Void kwUtlAddSduToBeFreedQueue(gCb, sdu)
1078 KwCb    *gCb;
1079 KwSdu   *sdu;
1080 #endif
1081 {
1082    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.sduLst), &(sdu->lstEnt));
1083    RETVOID;
1084 }
1085
1086 /**
1087  * @brief  Function to add a re-transmitted pdu to the to be freed list
1088  *
1089  *
1090  * @param[in]  gCb   RLC instance control block
1091  * @param[in]  retx  Re-transmitted pdu to be added to the list
1092  *
1093  * @return  Void
1094  */
1095 #ifdef ANSI
1096 PUBLIC Void kwUtlAddReTxPduToBeFreedQueue
1097 (
1098 KwCb     *gCb,
1099 KwRetx   *retx
1100 )
1101 #else
1102 PUBLIC Void kwUtlAddReTxPduToBeFreedQueue(gCb, retx)
1103 KwCb     *gCb;
1104 KwRetx   *retx;
1105 #endif
1106 {
1107    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.reTxLst), &(retx->lstEnt));
1108    RETVOID;
1109 }
1110
1111 /**
1112  * @brief  Function to add a transmitted pdu to the to be freed list
1113  *
1114  *
1115  * @param[in]  gCb   RLC instance control block
1116  * @param[in]  pdu   PDU to be added to the list
1117  *
1118  * @return  Void
1119  */
1120 #ifdef ANSI
1121 PUBLIC Void kwUtlAddTxPduToBeFreedQueue
1122 (
1123 KwCb   *gCb,
1124 KwTx   *pdu
1125 )
1126 #else
1127 PUBLIC Void kwUtlAddTxPduToBeFreedQueue(gCb, pdu)
1128 KwCb   *gCb;
1129 KwTx   *pdu;
1130 #endif
1131 {
1132    pdu->rlsLnk.node = (PTR)pdu;
1133    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.txLst), &(pdu->rlsLnk));
1134    RETVOID;
1135 }
1136
1137 /*
1138  * @brief
1139  *    function to free/release the Acknowledged mode RBCB buffers
1140  *
1141  * @details
1142  *    This primitive Frees the Acknowledged Mode RbCb transmission Buffer,
1143  *    retransmission Buffer and reciption Buffers
1144  *
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
1148  *
1149  * @return Bool
1150  *     - TRUE if more data to be freed
1151  *     - FALSE if all the data has been freed
1152  */
1153 #ifdef ANSI
1154 PRIVATE Bool kwUtlFreeDlAmRbMemory
1155 (
1156 KwCb       *gCb,
1157 KwDlRbCb   *rbCb,
1158 U32        *toBeFreed
1159 )
1160 #else
1161 PRIVATE Bool kwUtlFreeDlAmRbMemory(gCb, rbCb, toBeFreed)
1162 KwCb       *gCb;
1163 KwDlRbCb   *rbCb;
1164 U32        *toBeFreed
1165 #endif
1166 {
1167    KwRetx   *retx;   /* retransmission buffer */
1168    KwSn     mTxNext;    /* send state variable */
1169    KwTx      *txBuf;
1170
1171    TRC2(kwUtlFreeDlAmRbMemory)
1172
1173
1174    MODAMT(AMDL.txNext, mTxNext, AMDL.txNextAck,AMDL.snModMask);
1175
1176    /* TODO : to be checked changed from <= to < */
1177    while ((0 < mTxNext) && *toBeFreed)
1178    {
1179       txBuf =  kwUtlGetTxBuf(AMDL.txBufLst, AMDL.txNextAck);
1180       if (txBuf && txBuf->pduLst.first)
1181       {
1182          while(txBuf->pduLst.first)
1183          {
1184             KwDlPduInfo *pduInfo = (KwDlPduInfo *)(txBuf->pduLst.first->node);
1185             KW_FREE_BUF(pduInfo->pdu);
1186             /* Delete node from the txBuf Pdu lst */
1187             cmLListDelFrm(&txBuf->pduLst, txBuf->pduLst.first);
1188             KW_FREE_WC(gCb, pduInfo, sizeof(KwDlPduInfo));
1189          }
1190          kwUtlDelTxBuf(AMDL.txBufLst, txBuf, gCb);
1191          if(gCb->u.dlCb->shutdownReceived == 0)
1192          {   
1193             (*toBeFreed)--;
1194          }
1195       }
1196       AMDL.txNextAck = (AMDL.txNextAck + 1) & AMDL.snModMask;
1197       MODAMT(AMDL.txNext, mTxNext, AMDL.txNextAck,AMDL.snModMask);
1198    }
1199    if(*toBeFreed == 0)
1200    {
1201       RETVALUE(TRUE);
1202    }
1203    
1204 #ifndef LTE_TDD 
1205       KW_FREE(gCb,AMDL.txBufLst, (KW_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
1206 #endif
1207
1208    KW_LLIST_FIRST_RETX(AMDL.retxLst, retx);
1209    while (retx && (*toBeFreed)) /* Till to be freed becomes 0 */
1210    {
1211
1212       KW_FREE_BUF(retx->seg);
1213
1214       cmLListDelFrm(&AMDL.retxLst, &retx->lstEnt);
1215       KW_FREE_WC(gCb, retx, sizeof(KwRetx));
1216
1217       KW_LLIST_FIRST_RETX(AMDL.retxLst, retx);
1218       if(gCb->u.dlCb->shutdownReceived == 0)
1219       {
1220       (*toBeFreed)--;
1221    }
1222
1223    }
1224
1225    AMDL.nxtRetx = NULLP;
1226
1227    /* clean up if there is info about STATUS PDU to be sent */
1228    if(AMDL.pStaPdu)
1229    {
1230       Pst *udxPst;
1231       udxPst = &gCb->u.dlCb->udxDlSap->pst;
1232       KW_FREE_SHRABL_BUF_WC(udxPst->region,
1233                             udxPst->pool,
1234                             AMDL.pStaPdu, 
1235                             sizeof(KwUdxDlStaPdu));
1236       AMDL.pStaPdu = NULLP;
1237    }
1238
1239    if(*toBeFreed == 0)
1240    {
1241       RETVALUE(TRUE);
1242    }  
1243    if(gCb->u.dlCb->shutdownReceived)
1244    {   
1245       (*toBeFreed)--;
1246    }
1247    
1248    RETVALUE(FALSE);;
1249
1250
1251 /**
1252  * @brief  Function to free memory from the DL instance
1253  *
1254  *
1255  * @param[in]  gCb   RLC instance control block
1256  *
1257  * @return  Void
1258  */
1259 #ifdef ANSI
1260 PUBLIC Void kwUtlFreeDlMemory
1261 (
1262 KwCb *gCb  
1263 )
1264 #else
1265 PUBLIC Void kwUtlFreeDlMemory(gCb)
1266 KwCb *gCb;
1267 #endif
1268 {
1269    U32 toBeFreed; 
1270
1271    /* safety check, in case some event was still lying in the queue after
1272       the dlCb was deleted*/
1273    if(!gCb->u.dlCb)
1274    {
1275       RETVOID;
1276    }
1277
1278    KwDlDataToBeFreed* pToBeFreed = &gCb->u.dlCb->toBeFreed;
1279    /* ccpu00136940 */
1280    if(gCb->u.dlCb->shutdownReceived)
1281    {
1282       toBeFreed = pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count + pToBeFreed->rbLst.count; 
1283    }
1284    else
1285    {
1286       if ((pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count) > (3 * KW_MAX_TO_BE_FREED))
1287       {
1288 #if !defined(KWSELFPSTDLCLEAN) && defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
1289          if (isDatReqProcessed)
1290          {
1291             toBeFreed = (2 *KW_MAX_TO_BE_FREED);
1292          }
1293          else
1294 #endif
1295          {
1296             toBeFreed = (3 *KW_MAX_TO_BE_FREED)/2;
1297          }
1298       }
1299       else
1300       {
1301          toBeFreed = KW_MAX_TO_BE_FREED;
1302       }
1303    }   
1304    CmLListCp        *lst;
1305
1306    gCb->u.dlCb->eventInQueue = FALSE; /* reset as we have received the event
1307                                          and are processing it */
1308
1309    /* Free from the ReTx list */
1310    lst  = &pToBeFreed->reTxLst;
1311 #ifndef L2_OPTMZ
1312    while((lst->first) && toBeFreed && (pToBeFreed->reTxLst.count > 100))
1313 #else
1314    while((lst->first) && toBeFreed)
1315 #endif
1316    {
1317       KwRetx* seg = (KwRetx *)(lst->first->node);
1318       cmLListDelFrm(lst, lst->first);
1319       KW_FREE_BUF_WC(seg->seg);
1320       KW_FREE_WC(gCb,seg, sizeof(KwRetx));
1321       toBeFreed--;
1322    }   
1323
1324    /* Free from the Tx list */
1325    lst  = &pToBeFreed->txLst;
1326 #ifndef L2_OPTMZ
1327    while((lst->first) && toBeFreed && (pToBeFreed->txLst.count > 100))
1328 #else
1329    while((lst->first) && toBeFreed)
1330 #endif
1331    {
1332       KwTx* pdu = (KwTx *)(lst->first->node);
1333       cmLListDelFrm(lst, lst->first);
1334       while(pdu->pduLst.first)
1335       {
1336          KwDlPduInfo *pduInfo = (KwDlPduInfo *)(pdu->pduLst.first->node);
1337          
1338          cmLListDelFrm(&pdu->pduLst, pdu->pduLst.first);
1339          KW_FREE_BUF_WC(pduInfo->pdu);
1340          KW_FREE_WC(gCb, pduInfo, sizeof(KwDlPduInfo));
1341       }
1342       KW_FREE_WC(gCb,pdu, sizeof(KwTx));
1343       toBeFreed--;
1344    }
1345
1346    /* Free from the SDU queue */
1347    lst  = &pToBeFreed->sduLst;
1348 #ifndef L2_OPTMZ
1349    while((lst->first) && toBeFreed && (pToBeFreed->sduLst.count > 100))
1350 #else
1351    while((lst->first) && toBeFreed)
1352 #endif
1353    {
1354       KwSdu* sdu = (KwSdu *)(lst->first->node);
1355       KW_RMV_SDU(gCb, lst, sdu);
1356       toBeFreed--;
1357    }      
1358
1359    /* Free from the RBs */
1360    lst  = &pToBeFreed->rbLst;
1361 #ifndef L2_OPTMZ
1362    while((lst->first) && toBeFreed && (pToBeFreed->rbLst.count > 100))
1363 #else
1364    while((lst->first) && toBeFreed)
1365 #endif
1366    {
1367       KwDlRbCb* rbCb = (KwDlRbCb *)(lst->first->node);
1368       Bool moreToBeFreed = kwUtlFreeDlAmRbMemory(gCb, rbCb,&toBeFreed);
1369       if(!moreToBeFreed)
1370       {
1371          cmLListDelFrm(lst, lst->first);
1372          KW_FREE_WC(gCb, rbCb, sizeof(KwDlRbCb));
1373       }
1374    } 
1375
1376    if ((toBeFreed == 0) && !(gCb->u.dlCb->shutdownReceived))
1377    {
1378       kwUtlRaiseDlCleanupEvent(gCb);
1379    }
1380
1381    RETVOID;
1382 }
1383
1384
1385 #ifdef LTE_L2_MEAS
1386 /**
1387  *
1388  * @brief Function to initialise measurement
1389  *
1390  * @b Description
1391  *
1392  * @param[in]  gCb     RLC Instance Control Block
1393  *
1394  *  @return  Void
1395  *
1396  */
1397 S16 kwUtlL2MeasDlInit(KwCb *gCb)
1398 {
1399    U16   cntr;
1400
1401    gCb->u.dlCb->kwL2Cb.kwNumMeas=0;
1402    for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
1403    {
1404       cmMemset((U8 *)&(gCb->u.dlCb->kwL2Cb.kwL2EvtCb[cntr]), 0, sizeof(KwL2MeasEvtCb));
1405    }
1406    gCb->u.dlCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_DL_DISC].measCb.measType = LKW_L2MEAS_DL_DISC;
1407    gCb->u.dlCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_DL_IP].measCb.measType = LKW_L2MEAS_DL_IP;
1408    gCb->u.dlCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_DL_DELAY].measCb.measType= LKW_L2MEAS_DL_DELAY;
1409    gCb->u.dlCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_UU_LOSS].measCb.measType= LKW_L2MEAS_UU_LOSS;
1410    gCb->u.dlCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_ACT_UE].measCb.measType= LKW_L2MEAS_ACT_UE;
1411
1412    RETVALUE(ROK);
1413 }
1414 /**
1415  *
1416  * @brief Function to detect the data Burst start Condition in a DTCH
1417  *
1418  * @b Description
1419  *
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
1424  *
1425  *  @return  Void
1426  *
1427  */
1428 #ifdef ANSI
1429 PUBLIC Void kwUtlUpdateBurstSdus
1430 (
1431 KwCb            *gCb,
1432 KwDlRbCb        *rbCb,
1433 KwContSduLst    *contSduLst,
1434 S32             dataVol,
1435 U32             schPduSz
1436 )
1437 #else
1438 PUBLIC Void  kwUtlUpdateBurstSdus (gCb, rbCb, contSduLst, dataVol, schPduSz)
1439 KwCb            *gCb;
1440 KwDlRbCb        *rbCb;
1441 KwContSduLst    *contSduLst;
1442 S32             dataVol;
1443 U32             schPduSz;
1444 #endif
1445 {
1446
1447    KwL2MeasDlIpTh *l2MeasDlIpThruput = NULLP;
1448    KwL2MeasTb     *l2MeasTb = NULLP;
1449    U8              idx;
1450    U8              currTbIdx;
1451    VOLATILE U32     startTime = 0;
1452    KwContSduLst   *dstContSduLst;
1453    TRC2(kwUtlUpdateBurstSdus)
1454
1455
1456    /*starting Task*/
1457    SStartTask(&startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1458
1459    l2MeasDlIpThruput = &rbCb->l2MeasIpThruput.dlIpTh;
1460
1461    if(KW_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb, rbCb))
1462    {
1463       if(dataVol > schPduSz)
1464       {
1465          if(l2MeasDlIpThruput->isBurstAct == FALSE)
1466          {
1467             l2MeasDlIpThruput->burstStartTime = glblTtiCnt;
1468             l2MeasDlIpThruput->isBurstAct = TRUE;
1469             l2MeasDlIpThruput->burstEndSduId = 0;
1470          }
1471          else
1472          {  /* This is the case when another burst started before RLC gets the 
1473                l2MeasDlIpThruput->burstEndSduId = 0; */
1474          }
1475       }
1476       else
1477       {  /* Store the burstEndSduId here */
1478          if((l2MeasDlIpThruput->isBurstAct == TRUE) &&
1479                (!l2MeasDlIpThruput->burstEndSduId))
1480          {
1481             l2MeasDlIpThruput->burstEndSduId = 
1482                l2MeasDlIpThruput->outStngSduArr[l2MeasDlIpThruput->lastSduIdx].sduId;
1483          }
1484       }
1485       if(l2MeasDlIpThruput->isBurstAct == TRUE)
1486       {
1487          l2MeasTb = kwUtlGetCurMeasTb(gCb,rbCb);
1488          /* Get the lChId from index 0, because index 0 is always for DL */
1489          if(l2MeasTb->numLcId >= KW_MAX_ACTV_DRB) 
1490          {
1491             /* ccpu00143043 */
1492             RETVOID;
1493          }
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];
1498          /* ccpu00143043 */
1499          for(idx = 0; ((idx < contSduLst->numSdus)
1500                   && (currTbIdx < KW_L2MEAS_MAX_OUTSTNGSDU)) ; idx++)
1501          {
1502             dstContSduLst->sduIdx[currTbIdx++] = contSduLst->sduIdx[idx];
1503          }
1504          l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus += idx;
1505          l2MeasTb->numLcId++;
1506       }/* End of isBurstAct */
1507    }/* End of if measOn */
1508
1509    /*stopping Task*/
1510    SStopTask(startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1511    RETVOID;
1512 }
1513 /**
1514  * @brief
1515  *        This function is used to store locally the sduIdx of the sdu in the 
1516  *        outstanding SDU array
1517  * 
1518  * @b Description:
1519  *        Stores the Sdu Idx in the contained  SDU Array and increments 
1520  *        the num contained  Sdus 
1521  *
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 
1524  *
1525  *  @return  Void
1526  */
1527 #ifdef ANSI
1528 PUBLIC Void kwUtlUpdateContainedSduLst
1529 (
1530 U8            sduIdx,
1531 KwContSduLst  *contSduLst
1532 )
1533 #else
1534 PUBLIC Void kwUtlUpdateContainedSduLst(sduIdx, contSduLst)
1535 U8            sduIdx;
1536 KwContSduLst  *contSduLst;
1537 #endif
1538 {
1539    if (contSduLst->numSdus < KW_L2MEAS_MAX_OUTSTNGSDU)
1540    {
1541     contSduLst->sduIdx[contSduLst->numSdus] = sduIdx;
1542     contSduLst->numSdus++;
1543    }
1544     RETVOID;
1545 }
1546
1547 /**
1548  * @brief
1549  *        This function is used to store the sduId of the sdu in the 
1550  *        outstanding SDU array
1551  * 
1552  * @b Description:
1553  *        Stores the Sdu Id in the outstanding SDU Array and increments 
1554  *        the num contained  Sdus 
1555  *
1556  *  @param[out] dlIpThPut  The structure in which the outstanding sdus are 
1557  *                         updated
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 
1561  *                      outstanding array  
1562  *
1563  *  @return  Void
1564  */
1565 #ifdef ANSI
1566 PUBLIC Void kwUtlUpdateOutStandingSduLst
1567 (
1568 KwL2MeasDlIpTh   *dlIpThPut, 
1569 U8               sduIdx, 
1570 MsgLen           sduLen, 
1571 U32              sduId,
1572 Bool             newIdx
1573 )
1574 #else
1575 PUBLIC Void kwUtlUpdateOutStandingSduLst(dlIpThPut, sduIdx, sduLen, sduId, newIdx)
1576 KwL2MeasDlIpTh   *dlIpThPut;
1577 U8               sduIdx;
1578 MsgLen           sduLen; 
1579 U32              sduId;
1580 Bool             newIdx;
1581 #endif
1582 {
1583    if (sduIdx < KW_L2MEAS_MAX_OUTSTNGSDU)
1584    {
1585    if(newIdx == TRUE)
1586    {      
1587      dlIpThPut->outStngSduArr[sduIdx].numTb = 0;
1588    }
1589    dlIpThPut->outStngSduArr[sduIdx].numTb++;
1590    dlIpThPut->outStngSduArr[sduIdx].sduId = sduId;
1591    dlIpThPut->outStngSduArr[sduIdx].sduLen = sduLen;
1592    }
1593    RETVOID;
1594 }
1595 #ifdef ANSI
1596 PUBLIC KwL2MeasTb * kwUtlGetCurMeasTb
1597 (
1598 KwCb     *gCb,
1599 KwDlRbCb *rbCb
1600 )
1601 #else
1602 PUBLIC KwL2MeasTb * kwUtlGetCurMeasTb(gCb, rbCb)
1603 KwCb     *gCb;
1604 KwDlRbCb *rbCb;
1605 #endif
1606 {
1607    KwL2MeasTb  *curL2MeasTb;
1608    U16         idx;
1609
1610    TRC3(kwUtlGetCurMeasTb)
1611       
1612    if((curL2MeasTb = rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx]) == NULLP)
1613       {
1614          /* Intentionally avoiding the KW_ALLOC macro to avoid  memset */
1615          if (SGetSBuf(gCb->init.region,
1616                   gCb->init.pool,
1617                   (Data **)&curL2MeasTb,
1618                   (Size)sizeof(KwL2MeasTb)) != ROK)
1619          {
1620             RETVALUE(NULLP);
1621          }
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 < KW_MAX_ACTV_DRB; idx++)
1628          {
1629             curL2MeasTb->sduInfo[idx].numSdus = 0;
1630          }
1631          for (idx = 0; idx < KW_MAX_ACTV_DRB; idx++)
1632          {
1633             curL2MeasTb->lchInfo[idx].numSdus = 0;
1634          }
1635       }
1636    RETVALUE(curL2MeasTb);
1637 }
1638
1639
1640 /**
1641  *
1642  * @brief Handler for Processing harq status indication
1643  *
1644  *
1645  * @b Description
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
1648  *        L2 Measurements.
1649  *
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.
1653  *
1654  *
1655  *  @return  S16
1656  *      -# ROK
1657  */
1658
1659 #ifdef ANSI
1660 PUBLIC S16 kwUtlProcHarqInd
1661 (
1662 KwCb             *gCb,
1663 RguHarqStatusInd *hqStaInd,
1664 KwDlUeCb           *ueCb,
1665 U8               tbIdx
1666 )
1667 #else
1668 PUBLIC S16 kwUtlProcHarqInd(gCb, hqStaInd, ueCb, tbIdx)
1669 KwCb             *gCb;
1670 RguHarqStatusInd *hqStaInd;
1671 KwDlUeCb           *ueCb;
1672 U8               tbIdx;
1673 #endif
1674 {
1675 #ifdef LTE_L2_MEAS
1676    KwDlRbCb       *kwRbCb;           /* KW Control Block */
1677    KwL2MeasTb   *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    KwOutStngSduInfo *outStngSduArr;  /* Outstanding sdu list */
1682    Ticks        ackTime;
1683    Ticks        delay;
1684    U32          totlSduCnt = 0;
1685 #endif
1686    U8           timeAddedFlag;
1687    S16          ret;
1688    VOLATILE U32     startTime = 0;
1689    /*kw005.201 Code added for DL IP thruput measurement*/
1690
1691    TRC3(kwUtlProcHarqInd)
1692
1693    /*starting Task*/
1694    SStartTask(&startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1695
1696    ret = ROK;
1697    if(hqStaInd->tbId[tbIdx] >= KW_INVALID_TBID)
1698    {
1699       RETVALUE(ROK);
1700    }
1701
1702    /* Find the L2 measurement tbCb to process DL Ip thruput*/
1703    l2MeasTb = ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]];
1704    if(l2MeasTb == NULLP)
1705    {
1706       RETVALUE(ROK);
1707    }
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 < KW_MAX_ACTV_DRB)); lcIdx++)
1712    {
1713       timeAddedFlag = FALSE;
1714       if((kwRbCb = ueCb->lCh[l2MeasTb->sduInfo[lcIdx].lcId - 1].dlRbCb)
1715             == NULLP)
1716       {
1717          continue;
1718       }
1719       /* fix for DL IP stop*/
1720       if (!gCb->u.dlCb->kwL2Cb.measOn[kwRbCb->qci]
1721             || (kwRbCb->rlcId.rbType == CM_LTE_SRB))
1722       {
1723          continue;
1724       }
1725       
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;
1729       /* ccpu00143043 */
1730       if ((numSdus >= KW_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1731       {
1732          break;
1733       }
1734       totlSduCnt += numSdus;
1735
1736       if (KW_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb,kwRbCb))
1737       {
1738          for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1739          {
1740             outStngSduArr =&(kwRbCb->l2MeasIpThruput.dlIpTh.outStngSduArr[\
1741                   l2MeasTb->sduInfo[lcIdx].sduIdx[sduIndx]]);
1742             if(hqStaInd->status[tbIdx] == TRUE)
1743             {
1744                /* If ACK is for burst End Sdu Id set burstActive 
1745                 * to FALSE  and accumulate time */
1746                if((kwRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId == 
1747                         outStngSduArr->sduId) && (outStngSduArr->numTb == 1))
1748                {
1749                   kwRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1750                   /*Update the l2Sts structure for calculating throughput*/
1751                   kwRbCb->rbL2Cb.l2Sts[KW_L2MEAS_DL_IP]->dlIpThruput.volSummation
1752                      += outStngSduArr->sduLen;
1753
1754                   kwRbCb->rbL2Cb.l2Sts[KW_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1755                      += glblTtiCnt - kwRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1756                   outStngSduArr->sduId = 0;
1757                   outStngSduArr->sduLen = 0;
1758                   outStngSduArr->numTb = 0;
1759                   kwRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1760                }
1761
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((kwRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE) &&
1765                      (--(outStngSduArr->numTb) == 0))
1766                {
1767                   kwRbCb->rbL2Cb.l2Sts[KW_L2MEAS_DL_IP]->dlIpThruput.volSummation
1768                      += outStngSduArr->sduLen;
1769
1770                   if(timeAddedFlag == FALSE)
1771                   {
1772                      kwRbCb->rbL2Cb.l2Sts[KW_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1773                         += glblTtiCnt - kwRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1774                      kwRbCb->l2MeasIpThruput.dlIpTh.burstStartTime = glblTtiCnt;
1775                      timeAddedFlag = TRUE;
1776                   }
1777                   outStngSduArr->sduId = 0;
1778                   outStngSduArr->sduLen = 0;
1779                }
1780             }/* End of status == TRUE */
1781             else
1782             {
1783                if(kwRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE)
1784                {
1785                   if((kwRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId == 
1786                            outStngSduArr->sduId))
1787                   {
1788                      kwRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1789                      kwRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1790                   }
1791                   /* Clear the outstanding sdu list */
1792                   outStngSduArr->sduId = 0;
1793                   outStngSduArr->sduLen = 0;
1794                   outStngSduArr->numTb = 0;
1795                }
1796             }
1797          }
1798       } 
1799    }
1800
1801    for(lcIdx = 0; ((lcIdx < l2MeasTb->numLchInfo) && (lcIdx < KW_MAX_ACTV_DRB)); lcIdx++)
1802    {
1803       if((kwRbCb = ueCb->lCh[l2MeasTb->lchInfo[lcIdx].lcId - 1].dlRbCb)
1804             == NULLP)
1805       {
1806          continue;
1807       }
1808       numSdus = l2MeasTb->lchInfo[lcIdx].numSdus;
1809       if ( numSdus == 0 )
1810       {
1811          continue;
1812       }
1813       /* ccpu00143043 */
1814       if ((numSdus > KW_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1815       {
1816          break;
1817       }
1818       /* Update stats */
1819       if(hqStaInd->status[tbIdx] == TRUE)
1820       {
1821          for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1822          {
1823             delay = KW_TIME_DIFF(ackTime,l2MeasTb->lchInfo[lcIdx].sduInfo[sduIndx].arvlTime);
1824             KW_UPD_PDCP_L2_DLDELAY_STS(gCb,kwRbCb, delay); 
1825          }
1826          /* Case of sduInfo not updated */
1827          if (totlSduCnt == 0)
1828          {
1829             totlSduCnt = numSdus;
1830          }
1831          KW_UPD_L2_UU_LOSS_POS_PKTS(gCb,kwRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1832       }
1833       else
1834       {
1835          /* Case of sduInfo not updated */
1836          if (totlSduCnt == 0)
1837          {
1838             totlSduCnt = numSdus;
1839          }
1840          KW_UPD_L2_UU_LOSS_PKTS(gCb,kwRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1841       }
1842    }
1843    /* Free this tb, deallocate the memory */
1844    KW_FREE(gCb, l2MeasTb, sizeof(KwL2MeasTb));
1845    ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]] = NULLP;
1846    
1847    /*stopping Task*/
1848    SStopTask(startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1849
1850    RETVALUE(ret);
1851 }/* end of  kwUtlProcHarqInd */ 
1852
1853 /**
1854  *
1855  * @brief Handler for Sending L2 Measurement confirm.
1856  *
1857  *
1858  * @b Description
1859  *        This function sends a consolidates the mesaurements taken during
1860  *        this time and sends the confirm .
1861  *
1862  *  @param[in] measEvtCb    Measurement Event Control Block.
1863  *
1864  *
1865  *  @return  S16
1866  *      -# ROK
1867  */
1868
1869 #ifdef ANSI
1870 PUBLIC S16 kwUtlSndDlL2MeasCfm
1871 (
1872 KwCb                  *gCb,
1873 KwL2MeasEvtCb         *measEvtCb
1874 )
1875 #else
1876 PUBLIC S16 kwUtlSndDlL2MeasCfm(gCb, measEvtCb)
1877 KwCb                  *gCb;
1878 KwL2MeasEvtCb         *measEvtCb;
1879 #endif
1880 {
1881    U32                     qciIdx;
1882    KwL2MeasCb              *measCb = NULLP;
1883    KwL2MeasCfmEvt          measCfmEvt;
1884    U32                     posPkts;
1885    U32                     dLoss;
1886
1887    U64                     dlDataVol;
1888    U64                     dlTime;
1889    U16                     cntr;
1890    /* Discard new changes starts */
1891    U8                      qci = 0;
1892    U32                     cfmIdx =0;
1893    /* Discard new changes ends */
1894
1895    TRC3(kwUtlSndL2MeasCfm)
1896
1897    /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
1898 #ifndef ALIGN_64BIT
1899    RLOG1(L_DEBUG,"kwUtlSndL2MeasCfm(transId(%ld))", measEvtCb->transId);
1900 #else
1901    RLOG1(L_DEBUG,"kwUtlSndL2MeasCfm(transId(%d))", measEvtCb->transId);
1902 #endif
1903
1904    /* Clean up the RB data structures */
1905    measCb = &measEvtCb->measCb;
1906    
1907    cmMemset((U8*)&measCfmEvt, 0, sizeof(KwL2MeasCfmEvt));
1908    measCfmEvt.transId = measEvtCb->transId;
1909
1910    measCfmEvt.measType = measCb->measType;
1911    measCfmEvt.status.status = LCM_PRIM_OK;
1912    measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
1913    
1914    if(measCb->measType & LKW_L2MEAS_DL_IP)
1915    {
1916       KwL2MeasCbUeMeasInfo *pUeInfoLstCb  = measCb->val.ipThMeas.ueInfoLst;
1917       KwL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
1918
1919       for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)        
1920       {
1921          pUeInfoLstCfm[cfmIdx].numCfm = 0;
1922          if (pUeInfoLstCb[cntr].isValid == TRUE)
1923          {
1924             pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
1925             pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
1926             for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)           
1927             {
1928                qci = pUeInfoLstCb[cntr].qci[qciIdx];
1929                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
1930
1931                dlDataVol = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation;
1932                dlTime = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation;
1933
1934                if((0 == dlTime) || !(gCb->u.dlCb->kwL2Cb.measOn[qci] & LKW_L2MEAS_DL_IP) )
1935                {
1936                   pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 0;
1937                }
1938                else
1939                {
1940                   pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 
1941                      (dlDataVol / dlTime);
1942                }
1943                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut *= 8;
1944
1945                /* Reset the values after reporting to Application */
1946                pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation = 0;
1947                pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation = 0;
1948
1949                measCfmEvt.val.ipThMeas.ueInfoLst[cfmIdx].numCfm++;
1950             }
1951             cfmIdx++;
1952          }
1953       }
1954       measCfmEvt.val.ipThMeas.numUes = cfmIdx; 
1955    }
1956    else
1957    {
1958       KwL2Cntr *pMeasData = measCb->val.nonIpThMeas.measData;
1959       KwL2MeasCfmNonIpThMeas *pMeasCfmNonIp = &measCfmEvt.val.nonIpThMeas;
1960
1961       pMeasCfmNonIp->numCfm = 0;
1962
1963       for(qciIdx = 0; qciIdx < LKW_MAX_QCI; qciIdx++)
1964       {
1965          qci = measCb->val.nonIpThMeas.qci[qciIdx];
1966          if (qci > 0)
1967          {
1968             pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].qci = qci;
1969
1970             if(measCb->measType & LKW_L2MEAS_UU_LOSS)
1971             {
1972                dLoss = pMeasData[qci].uuLoss.dLoss;
1973                posPkts = pMeasData[qci].uuLoss.posPkts;
1974                if(((posPkts + dLoss) != 0))
1975                {
1976                   pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.uuLoss  =
1977                      ((dLoss  * 1000000) / (posPkts + dLoss));
1978                }
1979                pMeasData[qci].uuLoss.dLoss = 0;
1980                pMeasData[qci].uuLoss.posPkts = 0;
1981             }
1982             if(measCb->measType & LKW_L2MEAS_DL_DISC)
1983             {
1984
1985                pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 0;
1986                if(pMeasData[qci].dlDisc.totSdus != 0)
1987                {
1988                   pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 
1989                      (((pMeasData[qci].dlDisc.discSdus)  * 1000000) / (pMeasData[qci].dlDisc.totSdus));
1990                }
1991
1992                pMeasData[qci].dlDisc.totSdus = 0;
1993                pMeasData[qci].dlDisc.discSdus = 0;
1994             }
1995             if(measCb->measType & LKW_L2MEAS_DL_DELAY)
1996             {
1997                if (pMeasData[qci].dlPjSduDelay.numSdus > 0)
1998                {
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;
2003                }
2004             }
2005             pMeasCfmNonIp->numCfm++;
2006          }
2007       }
2008    }
2009    /* Fix Klock warning */
2010    KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
2011    RETVALUE(ROK);
2012 } /* kwUtlSndL2MeasCfm */
2013 /**
2014  *
2015  * @brief Handler for Sending Negative confirm .
2016  *
2017  *
2018   @b Description
2019  *        This function is called when the l2 measurement cannot be started
2020  *        This function sends  negative confirm for all the requests
2021  *
2022  *  @param[in] measReqEvt    Measurement Req Structure
2023  *
2024  *
2025  *  @return  S16
2026  *      -# ROK
2027  */
2028
2029 #ifdef ANSI
2030 PUBLIC S16 kwUtlSndDlL2MeasNCfm
2031 (
2032 KwCb           *gCb,
2033 KwL2MeasReqEvt *measReqEvt,
2034 KwL2MeasCfmEvt *measCfmEvt
2035 )
2036 #else
2037 PUBLIC S16 kwUtlSndDlL2MeasNCfm(gCb,measReqEvt, measCfmEvt)
2038 KwCb           *gCb;
2039 KwL2MeasReqEvt *measReqEvt;
2040 KwL2MeasCfmEvt *measCfmEvt;
2041 #endif
2042 {
2043    TRC3(kwUtlSndDlL2MeasNCfm)
2044
2045    KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
2046    RETVALUE(ROK);
2047 } /* kwUtlSndL2MeasNCfm */
2048 /**
2049  *
2050  * @brief Handler for resetting the RB data structures
2051  *
2052  *
2053  * @b Description
2054  *        This function resets the RB data structure after the expiry of 
2055  *        measurement timer.
2056  *
2057  *  @param[in] measCb    Measurement Control Block.
2058  *
2059  *
2060  *  @return  Void
2061  */
2062 #ifdef ANSI
2063
2064 PUBLIC Void kwUtlResetDlL2MeasInKwRb
2065 (
2066 KwCb       *gCb,
2067 KwL2MeasCb *measCb,
2068 U8             measType
2069 )
2070 #else
2071 PUBLIC Void kwUtlResetDlL2MeasInKwRb(gCb, measCb, measType)
2072 KwCb       *gCb;
2073 KwL2MeasCb *measCb;
2074 U8             measType;
2075 #endif
2076 {
2077    U32           ueIdx;
2078    U32           qciIdx;
2079    KwDlUeCb      *ueCb = NULL;
2080
2081
2082
2083    if (measCb->measType & LKW_L2MEAS_DL_IP)
2084    {
2085       for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
2086       {           
2087          if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
2088          {
2089             for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
2090             {
2091                if (measType & LKW_L2MEAS_DL_IP)
2092                {
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->kwL2Cb.measOn[qciIdx] &= ~measType; 
2096                }
2097             }
2098
2099             if(ROK  != kwDbmFetchDlUeCb(gCb,measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
2100                      measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
2101             {
2102                continue;
2103             }
2104
2105          }
2106       }
2107    }
2108    else
2109    {
2110       /* for now the only meas should be DL discard in this case */
2111       if (measCb->measType & LKW_L2MEAS_DL_DISC)
2112       {
2113          U32 i;
2114          for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
2115          {
2116             U8 qciVal = measCb->val.nonIpThMeas.qci[i];
2117
2118             measCb->val.nonIpThMeas.measData[qciVal].dlDisc.discSdus = 0;
2119             measCb->val.nonIpThMeas.measData[qciVal].dlDisc.totSdus  = 0;
2120          }
2121          
2122       }
2123       if (measCb->measType & LKW_L2MEAS_DL_DELAY)
2124       {
2125          U32 i;
2126          for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
2127          {
2128             U8 qciVal = measCb->val.nonIpThMeas.qci[i];
2129
2130             measCb->val.nonIpThMeas.measData[qciVal].dlPjSduDelay.sduDelay = 0;
2131          }
2132       }
2133       measCb->val.nonIpThMeas.numQci = 0;
2134    }
2135 } /* kwUtlResetDlL2MeasInKwRb */
2136 #endif
2137
2138 PRIVATE Void dumpRLCDlRbInformation(KwDlRbCb* dlRbCb)
2139 {
2140    if(dlRbCb->mode == CM_LTE_MODE_UM)
2141    {
2142       RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2143                "UM Downlink UEID:%d CELLID:%d Q size = %d",
2144                        dlRbCb->rlcId.ueId,
2145                        dlRbCb->rlcId.cellId,
2146                        (int)dlRbCb->m.umDl.sduQ.count);
2147    }
2148    else if(dlRbCb->mode == CM_LTE_MODE_AM)
2149    {
2150       U32 j, numTxPdus=0;
2151       for(j = 0; j <= (KW_AM_GET_WIN_SZ(dlRbCb->m.amDl.snLen)); j++)
2152       {
2153          KwTx *txBuf = kwUtlGetTxBuf(dlRbCb->m.amDl.txBufLst, j);
2154          if(txBuf != NULLP)
2155          {
2156             numTxPdus++;
2157          }
2158       }
2159       RLOG_ARG4(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2160                "AM Downlink UEID:%d CELLID:%d Sizes SDU Q = %d TX Q = %d ",
2161                        dlRbCb->rlcId.ueId,
2162                        dlRbCb->rlcId.cellId,
2163                        (int)dlRbCb->m.amDl.sduQ.count,
2164                        (int)numTxPdus);
2165       RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
2166                "AM Downlink UEID:%d CELLID:%d RETX Q= %d",
2167                        dlRbCb->rlcId.ueId,
2168                        dlRbCb->rlcId.cellId,
2169                        (int)dlRbCb->m.amDl.retxLst.count);
2170    }
2171 }
2172
2173 Void DumpRLCDlDebugInformation(Void)
2174 {
2175    KwCb* dlInst = kwCb[1]; /* TODO : Check whether DL is 0 or 1 */
2176
2177    KwDlCb *dlCb = dlInst->u.dlCb;
2178
2179    KwDlUeCb *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, 
2184                                    (PTR) ueCb, 
2185                                    (PTR *)&ueCb))
2186    {
2187       U32 i;
2188       for(i = 0; i< KW_MAX_SRB_PER_UE; i++)
2189       {
2190          KwDlRbCb* dlRbCb = ueCb->srbCb[i]; 
2191          if( dlRbCb != NULLP)
2192          {
2193             dumpRLCDlRbInformation(dlRbCb);
2194          }
2195       }
2196       for(i = 0; i< KW_MAX_DRB_PER_UE; i++)
2197       {
2198          KwDlRbCb* dlRbCb = ueCb->drbCb[i]; 
2199          if( dlRbCb != NULLP)
2200          {
2201             dumpRLCDlRbInformation(dlRbCb);
2202          }
2203       }
2204    }
2205
2206    KwDlDataToBeFreed* pToBeFreed = &dlCb->toBeFreed;
2207
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);
2212 }
2213
2214 /**
2215  *
2216  * @b Description
2217  *        This function frees downlink memory 
2218  *
2219  *  @param[in] Void
2220  *
2221  *
2222  *  @return  Void
2223  */
2224
2225 #ifdef ANSI
2226 void kwUtlFreeDlMem
2227 (
2228  Void
2229 )
2230 #else
2231 void kwUtlFreeDlMem()
2232 Void;
2233 #endif
2234 {
2235   kwUtlFreeDlMemory(KW_GET_KWCB(KW_DL_INST));
2236 }
2237
2238 /**
2239  *
2240  * @b Description
2241  *        This function returns current time
2242  *
2243  *  @param[in] U32 
2244  *
2245  *
2246  *  @return  Void
2247  */
2248
2249 #ifdef ANSI
2250 void kwUtlGetCurrTime
2251 (
2252  U32  *currTime
2253 )
2254 #else
2255 void kwUtlGetCurrTime(U32 *currTime)
2256 U32   *currTime;
2257 #endif
2258 {
2259    TRC2(kwUtlGetCurrTime)
2260
2261    /* Need t define else part for PAL */
2262    *currTime = SGetTtiCount();
2263 }
2264
2265 #if defined(MAC_RLC_HARQ_STA_RBUF) || defined (SS_RBUF)
2266 #ifdef LTE_L2_MEAS
2267 #ifdef ANSI
2268 void kwUtlDlBatchProcHqStaInd
2269 (
2270  Void
2271 )
2272 #else
2273 void kwUtlDlBatchProcHqStaInd()
2274 Void;
2275 #endif
2276 {
2277    /* Read from Ring Buffer and process PDCP packets */
2278    //Pst pst = {0};
2279
2280    Void *elmIndx = NULLP;
2281    RguHarqStaInd *staInd = NULLP;
2282
2283 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2284    isDatReqProcessed = TRUE;
2285 #endif
2286    elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ);
2287    while(NULLP != elmIndx)
2288    {
2289       staInd = (RguHarqStaInd *)elmIndx;
2290       KwLiRguHqStaInd(&(staInd->pst), 0, &(staInd->hqStatusInd));
2291
2292       elmIndx = NULLP;
2293       staInd  = NULLP;
2294       SRngIncrRIndx(SS_RNG_BUF_MAC_HARQ);
2295
2296       if((elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ)) == NULLP)
2297       {
2298 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2299          isDatReqProcessed = FALSE;
2300 #endif
2301          break;
2302       }
2303    }
2304 }
2305 #endif
2306 #endif
2307
2308 /**
2309  * @brief evaluate and trigger PDB based flow control to PDCP 
2310  *
2311  * @details 
2312  *
2313  * @param[in]   rbCb  RB control block 
2314  *
2315  *
2316  *  @return  Void
2317  *
2318  */
2319 #ifdef ANSI
2320 PUBLIC Void kwUtlTrigPdbFlowCntrl
2321 (
2322 KwCb       *gCb,
2323 KwDlRbCb   *rbCb,
2324 U32        pktAdmitCnt
2325 )
2326 #else
2327 PUBLIC Void kwUtlTrigPdbFlowCntrl(gCb,rbCb,pktAdmitCnt)
2328 KwCb       *gCb;
2329 KwDlRbCb   *rbCb;
2330 U32        pktAdmitCnt;
2331 #endif
2332 {
2333    KwuFlowCntrlIndInfo    *flowCntrlInfo;
2334    KwKwuSapCb*            kwuSap;
2335
2336    kwuSap = gCb->u.dlCb->kwuDlSap + KW_UI_PDCP;
2337
2338    KW_SHRABL_STATIC_BUF_ALLOC(kwuSap->pst.region, 
2339                               kwuSap->pst.pool, 
2340                               flowCntrlInfo, 
2341                               sizeof(KwuFlowCntrlIndInfo));
2342    flowCntrlInfo->rlcId       = rbCb->rlcId;
2343    flowCntrlInfo->pktAdmitCnt = pktAdmitCnt;
2344    KwUiKwuFlowCntrlInd(&kwuSap->pst, kwuSap->suId, flowCntrlInfo);
2345 }
2346
2347 /**
2348  *
2349  * @brief Store the DL buffer in hashList  
2350  *
2351  *
2352  * @b Description
2353  *
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 
2358  *
2359  *
2360  *  @return  Void
2361  */
2362 #ifdef ANSI
2363 PUBLIC Void kwUtlStoreTxBuf 
2364 (
2365 CmLListCp        *txBufLst,
2366 KwTx             *txBuf,
2367 KwSn              sn
2368 )
2369 #else
2370 PUBLIC Void kwUtlStoreTxBuf(txBufLst, txBuf, sn)
2371 CmLListCp        *txBufLst;
2372 KwTx             *txBuf;
2373 KwSn              sn;
2374 #endif
2375 {
2376    U32             hashKey; 
2377
2378    TRC3(kwUtlStoretxBuf)
2379    //printf("S-sn(%d)\n", sn);
2380    hashKey = (sn % KW_TX_BUF_BIN_SIZE );
2381    txBuf->sn = sn; 
2382    txBuf->lnk.node = (PTR)txBuf;
2383    cmLListAdd2Tail(&(txBufLst[hashKey]), &txBuf->lnk);
2384
2385    RETVOID;
2386 } /* kwUtlStoreRecBuf */
2387
2388 /**
2389  *
2390  * @brief Retrieve the DL buffer from the list
2391  *
2392  *
2393  * @Description
2394  *
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 
2398  *
2399  *
2400  *  @return  Void
2401  */
2402 #ifdef ANSI
2403 PUBLIC KwTx* kwUtlGetTxBuf 
2404 (
2405 CmLListCp        *txBufLst,
2406 KwSn             sn
2407 )
2408 #else
2409 PUBLIC KwTx* kwUtlGetTxBuf(txBufLst, sn)
2410 CmLListCp        *txBufLst;
2411 KwSn             sn;
2412 #endif
2413 {
2414    U32                 hashKey; 
2415    CmLListCp           *txBufLstCp;
2416    KwTx                *txBuf;
2417    CmLList             *node = NULLP;
2418
2419    TRC3(kwUtlGetTxBuf)
2420    //printf("G-sn(%d)\n", sn);
2421
2422    hashKey = (sn % KW_TX_BUF_BIN_SIZE ); 
2423  
2424    txBufLstCp = &txBufLst[hashKey];
2425    CM_LLIST_FIRST_NODE(txBufLstCp, node);
2426    while(node)
2427    {
2428       txBuf = (KwTx *) node->node;
2429       if(txBuf->sn == sn)
2430       {
2431          RETVALUE(txBuf);
2432       }
2433       CM_LLIST_NEXT_NODE(txBufLstCp, node);
2434    }
2435    RETVALUE(NULLP);
2436 } /* kwUtlStoreTxBuf */
2437 /**
2438  *
2439  * @brief Delete the DL buffer from the list
2440  *
2441  *
2442  * @Description
2443  *
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 
2447  *
2448  *
2449  *  @return  Void
2450  */
2451 #ifdef ANSI
2452 PUBLIC Void kwUtlDelTxBuf 
2453 (
2454 CmLListCp        *txBufLst,
2455 KwTx            *txBuf,
2456 KwCb              *gCb                              
2457 )
2458 #else
2459 PUBLIC Void kwUtlDelTxBuf(txBufLst, txBuf, gCb)
2460 CmLListCp        *txBufLst;
2461 KwTx             *txBuf;
2462 KwCb             *gCb;                              
2463 #endif
2464 {
2465    U32                 hashKey; 
2466    CmLListCp           *txBufLstCp;
2467
2468    TRC3(kwUtlDelTxBuf)
2469
2470    hashKey = (txBuf->sn % KW_TX_BUF_BIN_SIZE ); 
2471  
2472    txBufLstCp = &txBufLst[hashKey];
2473    //printf("D-sn(%d)\n", txBuf->hdr.sn);
2474    cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2475    KW_FREE_WC(gCb, txBuf, sizeof(KwTx));
2476    RETVOID;
2477 } /* kwUtlDelTxBuf */
2478
2479 /**
2480  *
2481  * @brief Remove the DL buffer from the list
2482  *
2483  *
2484  * @Description
2485  *
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 
2489  *
2490  *
2491  *  @return  Void
2492  */
2493 #ifdef ANSI
2494 PUBLIC Void kwUtlRemovTxBuf 
2495 (
2496 CmLListCp        *txBufLst,
2497 KwTx            *txBuf,
2498 KwCb              *gCb                              
2499 )
2500 #else
2501 PUBLIC Void kwUtlRemovTxBuf(txBufLst, txBuf, gCb)
2502 CmLListCp        *txBufLst;
2503 KwTx             *txBuf;
2504 KwCb             *gCb;                              
2505 #endif
2506 {
2507    U32                 hashKey; 
2508    CmLListCp           *txBufLstCp;
2509
2510    TRC3(kwUtlRemovTxBuf)
2511
2512    hashKey = (txBuf->sn % KW_TX_BUF_BIN_SIZE ); 
2513  
2514    txBufLstCp = &txBufLst[hashKey];
2515    //printf("D-sn(%d)\n", txBuf->hdr.sn);
2516    cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2517    RETVOID;
2518 } /* kwUtlRemovTxBuf */
2519
2520
2521
2522 /********************************************************************30**
2523          End of file
2524 **********************************************************************/