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