daeb948ff4bc3c2936b2d7279aa47ec76a4ef021
[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                   --rlcUtlSendToMac
29                   --rlcUtlRcvFrmMac
30                   --rlcUtlEmptySduQ
31                   --rlcUtlSendDedLcBoStatus
32                   --rlcUtlSendUlDataToDu 
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 "rlc_utils.h"
75 #include "rlc_mac_inf.h"
76 #include "du_app_rlc_inf.h"
77 #include "rlc_lwr_inf_api.h"
78 #include "rlc_upr_inf_api.h"
79
80 #include "ss_rbuf.h"
81 #include "ss_rbuf.x" 
82
83 SsRngBufCnt rngCb;
84
85 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS))
86 uint32_t isDatReqProcessed;
87 #endif
88 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_DL) /* for debugging purpose */
89 #if (defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)) || defined (SS_RBUF)
90 void rlcUtlDlBatchProcHqStaInd ARGS ((Void));
91 #endif
92 Void ResetRLCStats(Void)
93 {
94    RlcCb* dlInst = rlcCb[1]; 
95    RlcCb* ulInst = rlcCb[0]; 
96    memset(&gRlcStats, 0, sizeof(RLCStats));
97    memset(&dlInst->genSts,0,sizeof(RlcGenSts));
98    memset(&ulInst->genSts,0,sizeof(RlcGenSts));
99 }
100
101 #ifndef ALIGN_64BIT
102 Void PrintRLCStats(Void)
103 {
104    RlcCb* dlInst = rlcCb[1]; 
105    RlcCb* ulInst = rlcCb[0]; 
106
107    RLOG4(L_ALWAYS,"RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)",
108                      dlInst->genSts.pdusSent,
109                      dlInst->genSts.pdusRetx,
110                      dlInst->genSts.protTimeOut,
111                      dlInst->genSts.numSduDisc);
112    RLOG3(L_ALWAYS,"RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)",
113                      ulInst->genSts.pdusRecv,
114                      ulInst->genSts.unexpPdusRecv,
115                      ulInst->genSts.errorPdusRecv);
116    RLOG4(L_ALWAYS,"RLC Stats: RLC_AMDL: "
117                      "StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu ",
118                      gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, 
119                      gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
120    RLOG3(L_ALWAYS,"RLC Stats: RLC_AMDL: "
121                      "DRB:%lu MaxRetx:%lu RetransPdus:%lu", 
122                      gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx, 
123                      gRlcStats.amRlcStats.numDLRetransPdus);
124    RLOG4(L_ALWAYS,"RLC Stats: RLC_AMUL: "
125                      " PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu ", 
126                      gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires, 
127                      gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
128
129    RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)\n",
130                      dlInst->genSts.pdusSent,
131                      dlInst->genSts.pdusRetx,
132                      dlInst->genSts.protTimeOut,
133                      dlInst->genSts.numSduDisc);
134    RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)\n",
135                      ulInst->genSts.pdusRecv,
136                      ulInst->genSts.unexpPdusRecv,
137                      ulInst->genSts.errorPdusRecv);
138    RTLIN_DUMP_DEBUG("RLC Stats:"
139                     "RLC_AMDL: StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu DRB:%lu MaxRetx:%lu RetransPdus:%lu \n"
140                     "RLC_AMUL: PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu \n", 
141                      gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused, 
142                      gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx, 
143                      gRlcStats.amRlcStats.numDLRetransPdus, gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires, 
144                      gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
145 }
146 #else
147 Void PrintRLCStats(Void)
148 {
149    RlcCb* dlInst = rlcCb[1]; 
150    RlcCb* ulInst = rlcCb[0]; 
151
152    printf ("\n================================ RLC STATS ===========================\n");
153    RLOG4(L_ALWAYS,"RLC Stats: PDUs Sent = (%ld), PdusRext = (%ld), TimeOut = (%ld), SduDiscarded = (%ld)",
154                      dlInst->genSts.pdusSent,
155                      dlInst->genSts.pdusRetx,
156                      dlInst->genSts.protTimeOut,
157                      dlInst->genSts.numSduDisc);
158    RLOG3(L_ALWAYS,"RLC Stats: PDUs Rcvd = (%ld), unexpPdus = (%ld), errorPdus = (%ld)",
159                      ulInst->genSts.pdusRecv,
160                      ulInst->genSts.unexpPdusRecv,
161                      ulInst->genSts.errorPdusRecv);
162    RLOG4(L_ALWAYS,"RLC Stats: RLC_AMDL: "
163                      "StaPduSent:%lu NacksInStaPdu:%lu BytesUnused:%lu PollTimerExpires SRB:%lu ",
164                      gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, 
165                      gRlcStats.amRlcStats.numDLBytesUnused, gRlcStats.amRlcStats.numDLPollTimerExpiresSrb);
166    RLOG3(L_ALWAYS,"RLC Stats: RLC_AMDL: "
167                      "DRB:%lu MaxRetx:%lu RetransPdus:%lu", 
168                      gRlcStats.amRlcStats.numDLPollTimerExpiresDrb, gRlcStats.amRlcStats.numDLMaxRetx, 
169                      gRlcStats.amRlcStats.numDLRetransPdus);
170    RLOG4(L_ALWAYS,"RLC Stats: RLC_AMUL: "
171                      " PdusDiscarded:%lu ReOrdTimerExpires:%lu StaPduRcvd:%lu NackInStaPduRcvd:%lu ", 
172                      gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires, 
173                      gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd);
174  /*  RTLIN_DUMP_DEBUG("AM RLC Stats:"
175                     "RLC_AMDL: SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) MaxRetx:(%u) WindowStalls: (%u) \n"
176                     "RLC_AMUL: DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx :(%u) \n",
177                      gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
178                      gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmMaxRetx, gRlcStats.amRlcStats.numRlcAmCellWinStall,
179                      gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
180                      gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
181 */
182    RTLIN_DUMP_DEBUG("RLC Stats: PDUs Sent = (%d), PdusRext = (%d), TimeOut = (%d), SduDiscarded = (%d)\n",
183                      dlInst->genSts.pdusSent,
184                      dlInst->genSts.pdusRetx,
185                      dlInst->genSts.protTimeOut,
186                      dlInst->genSts.numSduDisc);
187    RTLIN_DUMP_DEBUG("RLC Stats: PDUs Rcvd = (%d), unexpPdus = (%d), errorPdus = (%d)\n",
188                      ulInst->genSts.pdusRecv,
189                      ulInst->genSts.unexpPdusRecv,
190                      ulInst->genSts.errorPdusRecv);
191    RTLIN_DUMP_DEBUG("RLC_AMDL: StaPduSent:%u NacksInStaPdu:%u BytesUnused:%u PollTimerExpires SRB:%u DRB:%u MaxRetx:%u RetransPdus:%u \n"
192                     "      SDUs Tx :(%u) SDU Bytes Tx :(%u) SDUs Retx :(%u) WindowStalls: (%u) \n"
193
194                     "RLC_AMUL: PdusDiscarded:%u ReOrdTimerExpires:%u StaPduRcvd:%u NackInStaPduRcvd:%u \n"
195                     "      DropOutWinRx :(%u) SDUs Rx :(%u) SDU Bytes Rx :(%u) SDUNack Rx :(%u) Duplicate Pdu Rx:(%u) \n", 
196                      gRlcStats.amRlcStats.numDLStaPduSent, gRlcStats.amRlcStats.numDLNacksInStaPdu, gRlcStats.amRlcStats.numDLBytesUnused, 
197                      gRlcStats.amRlcStats.numDLPollTimerExpiresSrb, gRlcStats.amRlcStats.numDLPollTimerExpiresDrb,
198                      gRlcStats.amRlcStats.numDLMaxRetx, gRlcStats.amRlcStats.numDLRetransPdus,
199                      gRlcStats.amRlcStats.numRlcAmCellSduTx, gRlcStats.amRlcStats.numRlcAmCellSduBytesTx,
200                      gRlcStats.amRlcStats.numRlcAmCellRetxPdu, gRlcStats.amRlcStats.numRlcAmCellWinStall,
201                      gRlcStats.amRlcStats.numULPdusDiscarded, gRlcStats.amRlcStats.numULReOrdTimerExpires, 
202                      gRlcStats.amRlcStats.numULStaPduRcvd, gRlcStats.amRlcStats.numULNackInStaPduRcvd,
203                      gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx, gRlcStats.amRlcStats.numRlcAmCellSduRx,
204                      gRlcStats.amRlcStats.numRlcAmCellSduBytesRx, gRlcStats.amRlcStats.numRlcAmCellNackRx, gRlcStats.amRlcStats.numRlcAmCellDupPduRx);
205 }
206 #endif
207
208 /*******************************************************************
209  *
210  * @brief 
211  *    Handler for storing all DL PDU Info into RLC-MAC interface
212  *    struct and sending to lower interface
213  *
214  * @details
215  *    This function stores DL PDU info for all logical channels
216  *    of per UE grant per TTI and sends to MAC
217  *
218  *    Function : rlcSendDedLcDlData 
219  *
220  * @params[in] 
221  * @return ROK     - success
222  *         RFAILED - failure
223  *
224  * ****************************************************************/
225 uint8_t rlcSendDedLcDlData(Pst *post, SpId spId, RguDDatReqInfo *datReqInfo)
226 {
227    uint8_t          ueIdx;      /* UE info list iterator */ 
228    uint8_t          tbIdx;      /* TB info list iterator */
229    uint8_t          lchIdx;     /* Lch info list iterator */
230    uint8_t          pduIdx;     /* RLC PDU list iterator */
231    RguDDatReqPerUe  datPerUe;   /* DL data info per UE */
232    RguDatReqTb      datPerTb;   /* DL data info per TB */
233    RguLchDatReq     datPerLch;  /* DL data info per Lch */
234    RlcData          *dlData;    /* DL data to be sent to MAC */
235    RlcDlRrcMsgRsp   *dlRrcMsgRsp;/* DL Data Msg Rsp sent to DU */
236    Pst              pst;        /* Post structure */
237    uint16_t         pduLen;     /* PDU length */
238    uint16_t         copyLen;    /* Number of bytes copied */
239
240    dlData = NULLP;
241    dlRrcMsgRsp = NULLP;
242    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
243                        dlData, sizeof(RlcData));
244    if ( dlData == NULLP )
245    {
246       DU_LOG("\nRLC: rlcSendDedLcDlData: Memory allocation failed for dl data");
247       RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
248           datReqInfo, sizeof(RguDDatReqInfo));
249       return RFAILED;
250    }
251
252    for(ueIdx = 0; ueIdx < datReqInfo->nmbOfUeGrantPerTti; ueIdx++)
253    {
254       datPerUe = datReqInfo->datReq[ueIdx];
255
256       memset(dlData, 0, sizeof(RlcData));
257
258       dlData->cellId = datReqInfo->cellId;
259       dlData->rnti = datPerUe.rnti;
260
261       /* Retrieving sfn/slot from transId. It was filled in RlcProcSchedResultRpt */
262       dlData->slotInfo.sfn = datPerUe.transId >> 16;
263       dlData->slotInfo.slot = datPerUe.transId & 0xffff;
264       dlData->numPdu = 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->numPdu].commCh = FALSE;
275                dlData->pduInfo[dlData->numPdu].lcId = datPerLch.lcId;
276
277                /* Copy Message to fixed buffer to send */
278                ODU_GET_MSG_LEN(datPerLch.pdu.mBuf[pduIdx], (MsgLen *)&pduLen);
279                RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
280                   dlData->pduInfo[dlData->numPdu].pduBuf, pduLen);
281
282                if (dlData->pduInfo[dlData->numPdu].pduBuf == NULLP )
283                {
284                   DU_LOG("\nRLC: rlcSendDedLcDlData: Memory allocation failed");
285                   for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
286                   {
287                      RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
288                        dlData->pduInfo[pduIdx].pduLen);
289                   }
290                   RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
291                      dlData, sizeof(RlcData));
292                   RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
293                      datReqInfo, sizeof(RguDDatReqInfo));
294                   return RFAILED;
295                }
296
297                ODU_COPY_MSG_TO_FIX_BUF(datPerLch.pdu.mBuf[pduIdx], 0, pduLen, \
298                   dlData->pduInfo[dlData->numPdu].pduBuf, (MsgLen *)&copyLen);
299                dlData->pduInfo[dlData->numPdu].pduLen = pduLen;
300
301                /* Free message */
302                ODU_PUT_MSG_BUF(datPerLch.pdu.mBuf[pduIdx]);
303
304                dlData->numPdu++;
305             }/* For per PDU */
306          }/* For Data per Lch */
307       }/* For Data per Tb */
308
309       RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
310                      dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
311       if( dlRrcMsgRsp == NULLP )
312       {
313          DU_LOG("\nRLC: rlcSendDedLcDlData: Memory allocation failed for dlRrcMsgRsp");
314          for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
315          {
316             RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
317                dlData->pduInfo[pduIdx].pduLen);
318          }
319           RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
320          RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
321              datReqInfo, sizeof(RguDDatReqInfo));
322          return RFAILED;
323       }
324
325       dlRrcMsgRsp->cellId = dlData->cellId;
326       dlRrcMsgRsp->crnti = dlData->rnti;
327
328       /* Sending DL Data per UE to MAC */
329       memset(&pst, 0, sizeof(Pst));
330       FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_DL_DATA_TO_MAC);
331       if(RlcSendDlDataToMac(&pst, dlData) != ROK)
332       {
333          for(pduIdx = 0; pduIdx < dlData->numPdu; pduIdx++)
334          {
335             RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData->pduInfo[pduIdx].pduBuf,\
336                dlData->pduInfo[pduIdx].pduLen);
337          }
338          RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlData, sizeof(RlcData));
339          /* Update DL RRC MSG Rsp State */
340          dlRrcMsgRsp->state = TRANSMISSION_FAILED;
341       }
342       else
343          dlRrcMsgRsp->state = TRANSMISSION_COMPLETE;
344
345       /* Send Dl RRC Msg Rsp to DU APP */
346       FILL_PST_RLC_TO_DUAPP(pst, RLC_DL_INST, EVENT_DL_RRC_MSG_RSP_TO_DU);
347       if(rlcSendDlRrcMsgRspToDu(&pst, dlRrcMsgRsp) != ROK)
348       {
349          RLC_FREE_SHRABL_BUF(pst.region, pst.pool, dlRrcMsgRsp, sizeof(RlcDlRrcMsgRsp));
350       }
351    } /* For Data per UE */
352
353    RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
354             datReqInfo, sizeof(RguDDatReqInfo));
355    
356    return ROK;
357 }/* End of rlcSendDedLcDlData */
358
359 /**
360  *
361  * @brief 
362  *        Handler for sending the data to multiple logical channels of a UE
363  *
364  * @details:
365  *        This function sends the data for one or more logical channels
366  *        after processing the SDUs and forming the PDUs.It calls
367  *        UMM or AMM functions to form the PDUs for the requested sizes
368  *        by MAC. 
369  *
370  * @param[in] gCb          RLC instance Control block 
371  * @param[in] staIndInfo   Status Indication Information containing the 
372  *                         size of PDU(s) for one or more logical channels  
373  *
374  * @return  S16
375  *      -# ROK 
376  *      -# RFAILED
377  *
378  */
379 uint8_t rlcUtlSendToMac(RlcCb *gCb, SuId suId, KwDStaIndInfo *staIndInfo)
380 {
381    uint8_t           numPdu = 0;
382    uint16_t          ueIdx;
383    RlcDlUeCb         *ueCb;         /* UE control block */
384    uint32_t          count;         /* Loop Counter */
385    uint32_t          numTb;         /* Number of Tbs */
386    RlcDlRbCb         *rbCb;         /* RB Control Block */
387    RlcDatReq         datReq;        /* PDUs Information */
388    RguDDatReqInfo   *datReqInfo;   /* Data Request Information */
389    RlcRguSapCb      *rguSap;       /* MAC SAP CB */
390    uint32_t         totNumPdu;     /* Total number of PDUS */
391    RguStaIndTb      *staIndTb = NULLP;
392    RguDatReqTb      *datReqTb = NULLP;
393    RguDStaIndPerUe  *staInd = NULLP;
394 #ifdef LTE_L2_MEAS   
395    uint32_t   grantPerLch[RGU_MAX_LC] = {0};
396 #endif
397 /* kw005.201 added support for L2 Measurement */
398 #ifdef LTE_L2_MEAS_LOSS_DELAY
399    uint8_t        snIdx1;
400    uint8_t        snIdx2;
401 #endif /* LTE_L2_MEAS */
402    uint32_t  idx;
403
404 //Debug
405    uint32_t staIndSz=0,datIndSz = 0;
406
407    datReqInfo = NULLP;
408    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL,
409                        datReqInfo,sizeof(RguDDatReqInfo));
410 #if (ERRCLASS & ERRCLS_ADD_RES)
411       if ( datReqInfo == NULLP )
412       {
413          DU_LOG("\nRLC: rlcUtlSendToMac: Memory allocation failed");
414          return RFAILED;
415       }
416 #endif /* ERRCLASS & ERRCLS_ADD_RES */
417    for(idx = 0; idx < staIndInfo->nmbOfUeGrantPerTti; idx++)
418    {
419       staInd = &staIndInfo->staInd[idx];
420       /* Fetch Ue control block */
421       GET_UE_IDX(staInd->rnti, ueIdx);
422       if(ROK != rlcDbmFetchDlUeCb(gCb, ueIdx, staIndInfo->cellId,&ueCb))
423       {
424          /* Fetch UeCb failed */
425          DU_LOG("\nRLC: rlcUtlSendToMac: UeId[%u]:ueCb not found",
426             staInd->rnti);
427          /* If ueCb is not found for current rnti then continue to look for next rnti*/
428          continue; 
429       }
430       /* kw002.201 Removed the allocation of RlcDatReq */
431       /* kw004.201 Used SSI function to initialize the variable */
432       memset(&datReq, 0, sizeof(RlcDatReq) ); 
433       totNumPdu = 0;
434       for (numTb = 0; numTb < staInd->nmbOfTbs; numTb++)
435       {
436          staIndTb = &(staInd->staIndTb[numTb]);
437          datReqTb = &(datReqInfo->datReq[idx].datReqTb[numTb]);
438 #ifdef LTE_L2_MEAS
439          ueCb->tbIdx = (ueCb->tbIdx+1) % RLC_MAX_TB_PER_UE;
440 #endif   
441          for (count = 0;count < staIndTb->nmbLch; count++)
442          {
443 #ifdef LTE_L2_MEAS
444             /*Calculate the total grant size from MAC */
445             if((staIndTb->lchStaInd[count].lcId >= RGU_MAX_LC) 
446                 || (staIndTb->lchStaInd[count].lcId == 0))
447             {
448                /* TODO : Need to figure out why this is happening */
449                break;
450             }
451             else
452             {
453                grantPerLch[staIndTb->lchStaInd[count].lcId] += staIndTb->lchStaInd[count].totBufSize;
454             }
455 #endif   
456             rbCb = ueCb->lCh[staIndTb->lchStaInd[count].lcId - 1].dlRbCb;
457
458             if (rbCb && (!rlcDlUtlIsReestInProgress(rbCb)))
459             { 
460 //Debug
461                staIndSz += staIndTb->lchStaInd[count].totBufSize;
462                datReq.pduSz = staIndTb->lchStaInd[count].totBufSize;
463 #ifdef LTE_L2_MEAS            
464                datReq.totMacGrant = grantPerLch[staIndTb->lchStaInd[count].lcId];
465 #endif
466                rlcUtlGetCurrTime(&datReq.boRep.oldestSduArrTime);
467                if ( CM_LTE_MODE_UM == rbCb->mode )
468                {
469                   rlcUmmProcessSdus(gCb,rbCb,&datReq);
470                }
471                else if ( CM_LTE_MODE_AM == rbCb->mode )
472                {
473                   rlcAmmProcessSdus(gCb,rbCb,&datReq,staInd->fillCtrlPdu);
474                }
475 #ifdef LTE_L2_MEAS            
476                grantPerLch[staIndTb->lchStaInd[count].lcId] = datReq.totMacGrant;
477 #endif
478                if ( 0 == datReq.pduInfo.numPdu )
479                {
480                   continue;
481                }
482                totNumPdu += datReq.pduInfo.numPdu;
483                memcpy(&(datReqTb->lchData[count].pdu),
484                   &(datReq.pduInfo),sizeof(KwPduInfo));
485
486                for (;numPdu < datReqTb->lchData[count].pdu.numPdu ; numPdu ++)
487                {
488                   MsgLen len = 0;
489                   ODU_GET_MSG_LEN(datReqTb->lchData[count].pdu.mBuf[numPdu],&len);
490                   datIndSz += len; 
491                }
492                datReqTb->lchData[count].setMaxUlPrio = FALSE;
493                if (RLC_AM_IS_POLL_BIT_SET(RLC_AMDL) && 
494                    (RLC_AMDL.sduQ.count > 1))
495                { 
496                   /* Poll bit is set indicate to MAC*/
497                   datReqTb->lchData[count].setMaxUlPrio = TRUE;
498                }
499                datReqTb->lchData[count].boReport.bo = datReq.boRep.bo;
500
501 #ifdef CCPU_OPT
502                datReqTb->lchData[count].boReport.estRlcHdrSz = 
503                   datReq.boRep.estHdrSz;
504                datReqTb->lchData[count].boReport.staPduPrsnt = 
505                   datReq.boRep.staPduPrsnt;
506 #endif /* CCPU_OPT */
507                datReqTb->lchData[count].boReport.staPduBo = 
508                   datReq.boRep.staPduBo;
509                datReqTb->lchData[count].lcId = staIndTb->lchStaInd[count].lcId;
510
511 #ifdef L2_OPTMZ
512                /* Set if Bearer is UM */
513                if ( CM_LTE_MODE_UM == rbCb->mode )
514                {
515                   datReqTb->lchData[count].freeBuff = TRUE;
516                }
517                else
518                {
519                   datReqTb->lchData[count].freeBuff = FALSE;
520                }
521 #endif
522
523                /* kw005.201 added support for L2 Measurement */
524 #ifdef LTE_L2_MEAS_LOSS_DELAY
525                datReqTb->rguSnInfo->lchMap[count].lChId =
526                   staIndTb->lchStaInd[count].lcId;
527                /* In some cases L2 Measurement for few of the lcId may be off, 
528                 * in this case we are assigning snList to 0xffff 
529                 */
530                for(snIdx1 = 0; snIdx1 < RGU_MAX_PDU; snIdx1++)
531                {
532                   datReqTb->rguSnInfo->lchMap[count].snList[snIdx1] = 0xffff;
533                }
534                if(tbSnMap->numSn != 0)
535                {
536                   snIdx2 = 0;
537                   for(snIdx1=tbSnMap->prevNumSn;snIdx1 < tbSnMap->numSn;snIdx1++)
538                   {
539                      datReqTb->rguSnInfo->lchMap[count].snList[snIdx2++] = 
540                         tbSnMap->snSduMap[snIdx1].sn;
541                   }
542                   tbSnMap->prevNumSn = tbSnMap->numSn;
543                }
544 #endif
545                datReqTb->lchData[count].boReport.oldestSduArrTime = 
546                                              datReq.boRep.oldestSduArrTime;
547                /* kw004.201 Used SSI function to initialize the variable */
548                memset(&datReq, 0, sizeof(RlcDatReq) ); 
549             }
550          }
551 #ifdef LTE_L2_MEAS
552          if(ueCb->l2MeasTbCb[ueCb->tbIdx]!= NULLP)
553          {
554             datReqTb->tbId = ueCb->tbIdx;
555          }
556          else
557          {
558             datReqTb->tbId = RLC_INVALID_TBID; 
559          }
560 #endif
561          datReqTb->nmbLch = staIndTb->nmbLch;
562          /*adding the check to make sure that lcId is not sent as 0
563           * when no data is there in datReq */
564          if ( 0 == totNumPdu )
565          {
566             datReqTb->lchData[0].lcId = staIndTb->lchStaInd[0].lcId;
567          }
568          /* kw005.201 added support for L2 Measurement */
569 #ifdef LTE_L2_MEAS_LOSS_DELAY
570          if(tbSnMap->numSn == 0)
571          {
572             RLC_FREE(tbSnMap,sizeof(RlcTbSnMap));
573             RLC_FREE(datReqTb->rguSnInfo,sizeof(RguSnMapInfo));
574             datReqTb->rguSnInfo = NULLP;
575             rlcCb.rlcL2Cb.curTbSnMap = NULLP;
576             datReqTb->snMapPres = FALSE;
577          }
578          else
579          {
580             cmHashListInsert(&(rlcCb.rlcL2Cb.tbHlCp),(PTR)tbSnMap,
581                   (uint8_t *) &(tbSnMap->tbId), (uint16_t)sizeof(tbSnMap->tbId));
582             rlcCb.rlcL2Cb.curTbSnMap = NULLP;
583          }
584 #endif /* LTE_L2_MEAS */
585       }
586       datReqInfo->datReq[idx].nmbOfTbs = staInd->nmbOfTbs;
587       datReqInfo->datReq[idx].transId = staInd->transId;
588       datReqInfo->datReq[idx].rnti    = staInd->rnti;
589    }
590    datReqInfo->cellId  = staIndInfo->cellId;
591    datReqInfo->nmbOfUeGrantPerTti = staIndInfo->nmbOfUeGrantPerTti;
592
593    rguSap = &(gCb->u.dlCb->rguDlSap[suId]);
594    rlcSendDedLcDlData(&rguSap->pst,rguSap->spId,datReqInfo); 
595    return ROK;
596 }
597
598 /**
599  *
600  * @brief 
601  *        Handler for sending Status Response to MAC. 
602  *
603  * @detail:
604  *        This function is used by  RLC entity for sending
605  *        status response to MAC after receiving a SDU from
606  *        PDCP.
607  *
608  * @param[in]  gCb           RLC instance Control block
609  * @param[in]  rbCb          Radio Bearer Control Block 
610  * @param[in]  bo            Buffer Occupancy
611  * @param[in]  estHdrSz      Estimated Header Size
612  * @param[in]  staPduPrsnt   Status PDU present or not
613  *
614  * @return  S16
615  *      -# ROK 
616  *      -# RFAILED
617  */
618 uint8_t rlcUtlSendDedLcBoStatus(RlcCb *gCb, RlcDlRbCb *rbCb, int32_t bo, \
619    int32_t estHdrSz, bool staPduPrsnt, uint32_t staPduBo)
620 {
621    Pst           pst;           /* Post info */
622    RlcBoStatus   *boStatus;      /* Buffer occupancy status information */
623
624 #ifndef TENB_ACC
625    if ((rbCb->lastRprtdBoToMac > (uint32_t)8000) && (rbCb->boUnRprtdCnt < (uint32_t)5) 
626        && (!staPduPrsnt) && ((CM_LTE_MODE_AM == rbCb->mode ) && (RLC_AMDL.nxtRetx == NULLP)))
627    {
628       rbCb->boUnRprtdCnt++;
629       return ROK;
630    }
631 #endif
632    rbCb->boUnRprtdCnt = (uint32_t)0;
633    rbCb->lastRprtdBoToMac = (uint32_t)bo;
634
635    RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_DL, RLC_POOL, \
636       boStatus, sizeof(RlcBoStatus));
637
638    boStatus->cellId = rbCb->rlcId.cellId;
639    boStatus->ueIdx = rbCb->rlcId.ueId;
640    boStatus->commCh = FALSE; 
641    boStatus->lcId = rbCb->lch.lChId;
642    boStatus->bo = bo;
643
644    FILL_PST_RLC_TO_MAC(pst, RLC_DL_INST, EVENT_BO_STATUS_TO_MAC);
645    /* Send Status Response to MAC layer */
646    if(RlcSendBoStatusToMac(&pst, boStatus) != ROK)
647    {
648       RLC_FREE_SHRABL_BUF(pst.region, pst.pool, boStatus, sizeof(RlcBoStatus));
649    }
650
651    return ROK;
652 }
653
654 /**
655  *
656  * @brief 
657  *        Handler for emptying the SDU queue. 
658  * 
659  * @detail:
660  *        This function is used to empty the SDU queue when
661  *        a re-establishment request is received from the 
662  *        upper layer.
663  *
664  * @param[in]  gCb    RLC instance control block
665  * @param[in]  rbCb   Radio bearer control block
666  * @param[in]  sduQ   SDU queue to be emptied
667  *
668  * @return Void 
669  */
670 /* kw005.201 added support for L2 Measurement */
671 #ifdef LTE_L2_MEAS_RLC
672 Void rlcUtlEmptySduQ
673 (
674 RlcCb        *gCb, 
675 RlcDlRbCb    *rbCb,
676 CmLListCp   *sduQ 
677 )
678 #else
679 Void rlcUtlEmptySduQ
680 (
681 RlcCb        *gCb,
682 CmLListCp   *sduQ 
683 )
684 #endif
685 {
686 #ifdef LTE_L2_MEAS_RLC
687    CmLListCp   *sduSnMapQ;             /* SDU Sequence number map queue */
688    CmLList     *firstSduSnMap;         /* First Node in SDU SnMap Queue */
689    RlcSduSnMap  *sduSnMap;              /* SDU Sn Map */
690
691    sduSnMapQ = NULLP;
692    firstSduSnMap = NULLP;
693    sduSnMap = NULLP;
694
695
696    sduSnMapQ = &rbCb->sduSnMapQ;
697    CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
698
699    while(firstSduSnMap)
700    {
701       sduSnMap = (RlcSduSnMap *)firstSduSnMap->node;
702       if(sduSnMap != NULLP)
703       {
704          cmLListDelFrm(&(rbCb->sduSnMapQ), &(sduSnMap->lstEnt));
705          RLC_FREE(sduSnMap, sizeof(RlcSduSnMap));
706          CM_LLIST_FIRST_NODE(sduSnMapQ, firstSduSnMap);
707       }
708       else
709       {
710          CM_LLIST_NEXT_NODE(sduSnMapQ, firstSduSnMap);
711       }
712    }
713 #endif
714    return;
715 }
716
717 /**
718  *
719  * @brief 
720  *    Handler for calculating the Length Indicator (LI) length for a SDU 
721  * 
722  * @detail:
723  *    This function is used to calculate the LI (Length Indicator) length
724  *    which has to be substracted from the pduSize to correctly match the
725  *    formed PDU(s) size with the  size requested by MAC.
726  *
727  * @param[in]      gCb      RLC instance control block 
728  * @param[in]      numLi    Number of LIs already present 
729  * @param[in]      msgLen   Size of the SDU
730  * @param[in/out]  pduSz    Size of the pDU to be formed
731  *
732  * @return  void 
733  */
734 void rlcUtlCalcLiForSdu(RlcCb *gCb, uint16_t numLi, MsgLen msgLen, int16_t *pduSz)
735 {
736    if ( (*pduSz > msgLen)  && (msgLen < RLC_2K_BYTE))
737    {
738       if(0 == (numLi & RLC_BIT0)) /* check if number of LIs are odd or even */
739       {  
740          /* if number of LI's are even 2 bytes needed */
741          *pduSz -= 2;
742       }
743       else
744       {
745          /* if number of LI's are odd one byte needed */
746          *pduSz -= 1;
747       }
748    }
749    return;
750 }
751
752 /**
753  *
754  * @brief 
755  *    Function to set that re-establishment has started for an RB
756  * 
757  * @detail:
758  *    This function is used to set the reestInProgress flag to TRUE.
759  *    This also sets the estimated header size to 0 and sends bo as
760  *    0 to MAC so that RLC does not need to transmit any data.
761  *    If the poll re-transmit timer is running for the RB;
762  *    it is stopped
763  *
764  * @param[in]      gCb      RLC instance control block 
765  * @param[in]      rbCb     RB for which re-establishment has started 
766  *
767  * @return  void 
768  */
769 Void rlcDlUtlSetReestInProgressForRB(RlcCb *gCb,RlcDlRbCb *rbCb)
770 {
771       
772    rbCb->reestInProgress = TRUE;
773    
774    if(rbCb->mode == CM_LTE_MODE_AM )
775    {
776       rbCb->m.amDl.estHdrSz = 0;
777
778       if(rlcChkTmr(gCb, (PTR)rbCb, RLC_EVT_AMDL_POLL_RETX_TMR))
779       {
780          rlcStopTmr(gCb, (PTR)rbCb, RLC_EVT_AMDL_POLL_RETX_TMR);
781       }
782    }
783    else
784    {
785       rbCb->m.umDl.estHdrSz= 0;
786    }
787
788    rlcUtlSendDedLcBoStatus(gCb, rbCb, 0, 0, FALSE,0);
789
790    return;
791 }
792
793 /**
794  *
795  * @brief 
796  *    Function to check if re-establishment is ongoing for an RB
797  * 
798  * @param[in]      rbCb     RB for which re-establishment is to be checked 
799  *
800  * @return  Bool
801  *          TRUE  : Re-establishment is in progress
802  *          FALSE : Re-establishment is not in progress
803  */
804 bool rlcDlUtlIsReestInProgress(RlcDlRbCb *rbCb)
805 {
806    return (rbCb->reestInProgress);
807 }
808
809 /**
810  *
811  * @brief 
812  *    Function to set re-establishment to FALSE
813  * 
814  * @param[in]      rbCb     RB for which re-establishment is to be reset 
815  *
816  * @return  Void
817  */
818 Void rlcDlUtlResetReestInProgress(RlcDlRbCb *rbCb)
819 {
820
821    rbCb->reestInProgress = FALSE;
822 }
823
824 /**
825  *
826  * @brief 
827  *    Function to set that re-establishment has started for all the RBs
828  *    of an UE; except for SRB1
829  *
830  * @detail: For SRB1 only the poll-retransmit timer is stopped
831  * 
832  * @param[in]      gCb      RLC instance control block 
833  * @param[in]      ueCb     UE for which re-establishment has started 
834  *
835  * @return  void 
836  */
837 Void rlcDlUtlSetReestInProgressForAllRBs(RlcCb *gCb,RlcDlUeCb *ueCb)
838 {
839    uint32_t        rbIdx;
840    
841    for(rbIdx = 0;rbIdx < RLC_MAX_SRB_PER_UE;rbIdx++)
842    {
843       if(ueCb->srbCb[rbIdx] != NULLP)
844       {
845          if(ueCb->srbCb[rbIdx]->rlcId.rbId != 1)
846          {
847             rlcDlUtlSetReestInProgressForRB(gCb,ueCb->srbCb[rbIdx]); 
848          }
849          else
850          {
851             /* For SRB we just need to stop the poll re-transmit timer */
852             if(rlcChkTmr(gCb, (PTR)ueCb->srbCb[rbIdx], RLC_EVT_AMDL_POLL_RETX_TMR))
853             {
854                rlcStopTmr(gCb, (PTR)ueCb->srbCb[rbIdx], RLC_EVT_AMDL_POLL_RETX_TMR);
855             }
856          }
857       }
858    }
859    
860    for(rbIdx = 0;rbIdx < RLC_MAX_DRB_PER_UE;rbIdx++)
861    {
862       if(ueCb->drbCb[rbIdx] != NULLP)
863       {
864          rlcDlUtlSetReestInProgressForRB(gCb,ueCb->drbCb[rbIdx]);
865       }
866    }
867       
868    return;
869 }
870
871 /**
872  * @brief  Function to increment number of SDUs transmitted 
873  *         in KWU SAP statistics
874  *
875  *
876  * @param[in]  rlckwuSap     KWU SAP in which to increment the counter
877  *
878  * @return  Void
879  */
880 void rlcUtlIncrementKwuStsSduTx(RlcKwuSapCb *rlckwuSap)
881 {
882    rlckwuSap->sts.sduTx++;
883    return;
884 }
885
886 /**
887  * @brief  Function to increment number of bytes and PDUs transmitted 
888  *         in General statistics
889  *
890  *
891  * @param[in]  genSts   KWU SAP in which to increment the counter
892  * @param[in]  pdu      The PDU which is sent
893  *
894  * @return  Void
895  */
896 void rlcUtlIncrementGenStsBytesAndPdusSent(RlcGenSts *genSts, Buffer *pdu)
897 {
898    MsgLen bytesSent;
899    ODU_GET_MSG_LEN(pdu, &bytesSent);
900    genSts->bytesSent += bytesSent;
901    genSts->pdusSent++;
902    return;
903 }
904
905 /**
906  * @brief  Function to initialize the data structures used to free memory
907  *
908  *
909  * @param[in]  gCb        RLC instance control block
910  * @param[out] toBeFreed  Pointer to the freeing structure. This is 
911  *                        initialized here
912  *
913  * @return  Void
914  */
915 Void rlcUtlInitToBeFreed(RlcCb *gCb,RlcDlDataToBeFreed *toBeFreed)
916 {
917    cmLListInit(&(toBeFreed->sduLst));
918    cmLListInit(&(toBeFreed->rbLst));
919    cmLListInit(&(toBeFreed->reTxLst));
920    cmLListInit(&(toBeFreed->txLst));
921    
922    return;
923 }
924
925 /**
926  * @brief  Function to initialize the DL self Pst structure
927  *
928  *
929  * @param[in]  gCb   RLC instance control block
930  *
931  * @return  Void
932  */
933 Void rlcUtlInitializeSelfPst(RlcCb *gCb)
934 {
935    Pst *selfPst = &gCb->u.dlCb->selfPst;
936    
937    RLC_MEM_SET(selfPst, 0, sizeof(Pst));
938    selfPst->srcProcId = SFndProcId();
939    selfPst->dstProcId = SFndProcId();
940    selfPst->dstEnt = gCb->init.ent;
941    selfPst->dstInst = gCb->init.inst; /* this is for the DL instance */
942    selfPst->srcEnt = gCb->init.ent;
943    selfPst->srcInst = gCb->init.inst;  /* DL instance will send to itself */
944    selfPst->prior  = PRIOR3;
945    selfPst->event  = UDX_EVT_DL_CLEANUP_MEM;
946 }
947
948 /**
949  * @brief  Function to send a DL cleanup event
950  *
951  *
952  * @param[in]  gCb   RLC instance control block
953  *
954  * @return  Void
955  */
956 void rlcUtlRaiseDlCleanupEvent(RlcCb *gCb)
957 {
958 #ifdef KWSELFPSTDLCLEAN
959    if(!gCb->u.dlCb->eventInQueue)
960    {
961       ODU_POST_TASK(&gCb->u.dlCb->selfPst, gCb->u.dlCb->selfPstMBuf);
962       gCb->u.dlCb->eventInQueue = TRUE;
963    }
964 #endif
965    return;
966 }
967
968 /**
969  * @brief  Function to add a SDU to the to be freed sdu list
970  *
971  *
972  * @param[in]  gCb   RLC instance control block
973  * @param[in]  sdu   SDU to be added to the list
974  *
975  * @return  Void
976  */
977 void rlcUtlAddSduToBeFreedQueue(RlcCb *gCb, RlcSdu *sdu)
978 {
979    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.sduLst), &(sdu->lstEnt));
980    return;
981 }
982
983 /**
984  * @brief  Function to add a re-transmitted pdu to the to be freed list
985  *
986  *
987  * @param[in]  gCb   RLC instance control block
988  * @param[in]  retx  Re-transmitted pdu to be added to the list
989  *
990  * @return  Void
991  */
992 Void rlcUtlAddReTxPduToBeFreedQueue(RlcCb *gCb,RlcRetx *retx)
993 {
994    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.reTxLst), &(retx->lstEnt));
995    return;
996 }
997
998 /**
999  * @brief  Function to add a transmitted pdu to the to be freed list
1000  *
1001  *
1002  * @param[in]  gCb   RLC instance control block
1003  * @param[in]  pdu   PDU to be added to the list
1004  *
1005  * @return  Void
1006  */
1007 Void rlcUtlAddTxPduToBeFreedQueue(RlcCb   *gCb,RlcTx   *pdu)
1008 {
1009    pdu->rlsLnk.node = (PTR)pdu;
1010    cmLListAdd2Tail(&(gCb->u.dlCb->toBeFreed.txLst), &(pdu->rlsLnk));
1011    return;
1012 }
1013
1014 /*
1015  * @brief
1016  *    function to free/release the Acknowledged mode RBCB buffers
1017  *
1018  * @details
1019  *    This primitive Frees the Acknowledged Mode RbCb transmission Buffer,
1020  *    retransmission Buffer and reciption Buffers
1021  *
1022  * @param [in]      gCb       - RLC instance control block
1023  * @param [in]      rbCb      - Downlink RB Control Block
1024  * @param [in,out]  toBeFreed - Number of buffers to be freed
1025  *
1026  * @return Bool
1027  *     - TRUE if more data to be freed
1028  *     - FALSE if all the data has been freed
1029  */
1030 static Bool rlcUtlFreeDlAmRbMemory(RlcCb *gCb,RlcDlRbCb *rbCb,uint32_t *toBeFreed)
1031 {
1032    RlcRetx   *retx;   /* retransmission buffer */
1033    RlcSn     mTxNext;    /* send state variable */
1034    RlcTx      *txBuf;
1035
1036    MODAMT(RLC_AMDL.txNext, mTxNext, RLC_AMDL.txNextAck,RLC_AMDL.snModMask);
1037
1038    /* TODO : to be checked changed from <= to < */
1039    while ((0 < mTxNext) && *toBeFreed)
1040    {
1041       txBuf =  rlcUtlGetTxBuf(RLC_AMDL.txBufLst, RLC_AMDL.txNextAck);
1042       if (txBuf && txBuf->pduLst.first)
1043       {
1044          while(txBuf->pduLst.first)
1045          {
1046             RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(txBuf->pduLst.first->node);
1047             ODU_PUT_MSG_BUF(pduInfo->pdu);
1048             /* Delete node from the txBuf Pdu lst */
1049             cmLListDelFrm(&txBuf->pduLst, txBuf->pduLst.first);
1050             RLC_FREE(gCb, pduInfo, sizeof(RlcDlPduInfo));
1051          }
1052          rlcUtlDelTxBuf(RLC_AMDL.txBufLst, txBuf, gCb);
1053          if(gCb->u.dlCb->shutdownReceived == 0)
1054          {   
1055             (*toBeFreed)--;
1056          }
1057       }
1058       RLC_AMDL.txNextAck = (RLC_AMDL.txNextAck + 1) & RLC_AMDL.snModMask;
1059       MODAMT(RLC_AMDL.txNext, mTxNext, RLC_AMDL.txNextAck,RLC_AMDL.snModMask);
1060    }
1061    if(*toBeFreed == 0)
1062    {
1063       return (TRUE);
1064    }
1065    
1066 #ifndef LTE_TDD 
1067       RLC_FREE(gCb,RLC_AMDL.txBufLst, (RLC_TX_BUF_BIN_SIZE * sizeof(CmLListCp)));
1068 #endif
1069
1070    RLC_LLIST_FIRST_RETX(RLC_AMDL.retxLst, retx);
1071    while (retx && (*toBeFreed)) /* Till to be freed becomes 0 */
1072    {
1073
1074       ODU_PUT_MSG_BUF(retx->seg);
1075
1076       cmLListDelFrm(&RLC_AMDL.retxLst, &retx->lstEnt);
1077       RLC_FREE(gCb, retx, sizeof(RlcRetx));
1078
1079       RLC_LLIST_FIRST_RETX(RLC_AMDL.retxLst, retx);
1080       if(gCb->u.dlCb->shutdownReceived == 0)
1081       {
1082       (*toBeFreed)--;
1083    }
1084
1085    }
1086
1087    RLC_AMDL.nxtRetx = NULLP;
1088
1089    /* clean up if there is info about STATUS PDU to be sent */
1090    if(RLC_AMDL.pStaPdu)
1091    {
1092       Pst *udxPst;
1093       udxPst = &gCb->u.dlCb->udxDlSap->pst;
1094       RLC_FREE_SHRABL_BUF_WC(udxPst->region,
1095                             udxPst->pool,
1096                             RLC_AMDL.pStaPdu, 
1097                             sizeof(RlcUdxDlStaPdu));
1098       RLC_AMDL.pStaPdu = NULLP;
1099    }
1100
1101    if(*toBeFreed == 0)
1102    {
1103       return (TRUE);
1104    }  
1105    if(gCb->u.dlCb->shutdownReceived)
1106    {   
1107       (*toBeFreed)--;
1108    }
1109    
1110    return (FALSE);
1111
1112
1113 /**
1114  * @brief  Function to free memory from the DL instance
1115  *
1116  *
1117  * @param[in]  gCb   RLC instance control block
1118  *
1119  * @return  Void
1120  */
1121 Void rlcUtlFreeDlMemory(RlcCb *gCb)
1122 {
1123    uint32_t toBeFreed; 
1124
1125    /* safety check, in case some event was still lying in the queue after
1126       the dlCb was deleted*/
1127    if(!gCb->u.dlCb)
1128    {
1129       return;
1130    }
1131
1132    RlcDlDataToBeFreed* pToBeFreed = &gCb->u.dlCb->toBeFreed;
1133    /* ccpu00136940 */
1134    if(gCb->u.dlCb->shutdownReceived)
1135    {
1136       toBeFreed = pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count + pToBeFreed->rbLst.count; 
1137    }
1138    else
1139    {
1140       if ((pToBeFreed->txLst.count + pToBeFreed->reTxLst.count + pToBeFreed->sduLst.count) > (3 * RLC_MAX_TO_BE_FREED))
1141       {
1142 #if !defined(KWSELFPSTDLCLEAN) && defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
1143          if (isDatReqProcessed)
1144          {
1145             toBeFreed = (2 *RLC_MAX_TO_BE_FREED);
1146          }
1147          else
1148 #endif
1149          {
1150             toBeFreed = (3 *RLC_MAX_TO_BE_FREED)/2;
1151          }
1152       }
1153       else
1154       {
1155          toBeFreed = RLC_MAX_TO_BE_FREED;
1156       }
1157    }   
1158    CmLListCp        *lst;
1159
1160    gCb->u.dlCb->eventInQueue = FALSE; /* reset as we have received the event
1161                                          and are processing it */
1162
1163    /* Free from the ReTx list */
1164    lst  = &pToBeFreed->reTxLst;
1165 #ifndef L2_OPTMZ
1166    while((lst->first) && toBeFreed && (pToBeFreed->reTxLst.count > 100))
1167 #else
1168    while((lst->first) && toBeFreed)
1169 #endif
1170    {
1171       RlcRetx* seg = (RlcRetx *)(lst->first->node);
1172       cmLListDelFrm(lst, lst->first);
1173       ODU_PUT_MSG_BUF(seg->seg);
1174       RLC_FREE(gCb,seg, sizeof(RlcRetx));
1175       toBeFreed--;
1176    }   
1177
1178    /* Free from the Tx list */
1179    lst  = &pToBeFreed->txLst;
1180 #ifndef L2_OPTMZ
1181    while((lst->first) && toBeFreed && (pToBeFreed->txLst.count > 100))
1182 #else
1183    while((lst->first) && toBeFreed)
1184 #endif
1185    {
1186       RlcTx* pdu = (RlcTx *)(lst->first->node);
1187       cmLListDelFrm(lst, lst->first);
1188       while(pdu->pduLst.first)
1189       {
1190          RlcDlPduInfo *pduInfo = (RlcDlPduInfo *)(pdu->pduLst.first->node);
1191          
1192          cmLListDelFrm(&pdu->pduLst, pdu->pduLst.first);
1193          ODU_PUT_MSG_BUF(pduInfo->pdu);
1194          RLC_FREE(gCb, pduInfo, sizeof(RlcDlPduInfo));
1195       }
1196       RLC_FREE(gCb,pdu, sizeof(RlcTx));
1197       toBeFreed--;
1198    }
1199
1200    /* Free from the SDU queue */
1201    lst  = &pToBeFreed->sduLst;
1202 #ifndef L2_OPTMZ
1203    while((lst->first) && toBeFreed && (pToBeFreed->sduLst.count > 100))
1204 #else
1205    while((lst->first) && toBeFreed)
1206 #endif
1207    {
1208       RlcSdu* sdu = (RlcSdu *)(lst->first->node);
1209       RLC_RMV_SDU(gCb, lst, sdu);
1210       toBeFreed--;
1211    }      
1212
1213    /* Free from the RBs */
1214    lst  = &pToBeFreed->rbLst;
1215 #ifndef L2_OPTMZ
1216    while((lst->first) && toBeFreed && (pToBeFreed->rbLst.count > 100))
1217 #else
1218    while((lst->first) && toBeFreed)
1219 #endif
1220    {
1221       RlcDlRbCb* rbCb = (RlcDlRbCb *)(lst->first->node);
1222       Bool moreToBeFreed = rlcUtlFreeDlAmRbMemory(gCb, rbCb,&toBeFreed);
1223       if(!moreToBeFreed)
1224       {
1225          cmLListDelFrm(lst, lst->first);
1226          RLC_FREE(gCb, rbCb, sizeof(RlcDlRbCb));
1227       }
1228    } 
1229
1230    if ((toBeFreed == 0) && !(gCb->u.dlCb->shutdownReceived))
1231    {
1232       rlcUtlRaiseDlCleanupEvent(gCb);
1233    }
1234
1235    return;
1236 }
1237
1238
1239 #ifdef LTE_L2_MEAS
1240 /**
1241  *
1242  * @brief Function to initialise measurement
1243  *
1244  * @b Description
1245  *
1246  * @param[in]  gCb     RLC Instance Control Block
1247  *
1248  *  @return  Void
1249  *
1250  */
1251 S16 rlcUtlL2MeasDlInit(RlcCb *gCb)
1252 {
1253    uint16_t   cntr;
1254
1255    gCb->u.dlCb->rlcL2Cb.rlcNumMeas=0;
1256    for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
1257    {
1258       memset(&(gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
1259    }
1260    gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DISC].measCb.measType = LKW_L2MEAS_DL_DISC;
1261    gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_IP].measCb.measType = LKW_L2MEAS_DL_IP;
1262    gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_DL_DELAY].measCb.measType= LKW_L2MEAS_DL_DELAY;
1263    gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UU_LOSS].measCb.measType= LKW_L2MEAS_UU_LOSS;
1264    gCb->u.dlCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_ACT_UE].measCb.measType= LKW_L2MEAS_ACT_UE;
1265
1266    return ROK;
1267 }
1268 /**
1269  *
1270  * @brief Function to detect the data Burst start Condition in a DTCH
1271  *
1272  * @b Description
1273  *
1274  * @param[in]  rbCb     RB control block
1275  * @param[in]  contSduLst  Array of Contained SDUs in the DTCH   
1276  * @param[in]  dataVol  Available data in the DTCH
1277  * @param[in]  schPduSz    Total grant Size given by MAC
1278  *
1279  *  @return  Void
1280  *
1281  */
1282 Void rlcUtlUpdateBurstSdus
1283 (
1284 RlcCb            *gCb,
1285 RlcDlRbCb        *rbCb,
1286 RlcContSduLst    *contSduLst,
1287 S32              dataVol,
1288 uint32_t         schPduSz
1289 )
1290 {
1291
1292    RlcL2MeasDlIpTh   *l2MeasDlIpThruput = NULLP;
1293    RlcL2MeasTb       *l2MeasTb = NULLP;
1294    uint8_t           idx;
1295    uint8_t           currTbIdx;
1296    volatile uint32_t startTime = 0;
1297    RlcContSduLst   *dstContSduLst;
1298
1299
1300    /*starting Task*/
1301    SStartTask(&startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1302
1303    l2MeasDlIpThruput = &rbCb->l2MeasIpThruput.dlIpTh;
1304
1305    if(RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb, rbCb))
1306    {
1307       if(dataVol > schPduSz)
1308       {
1309          if(l2MeasDlIpThruput->isBurstAct == FALSE)
1310          {
1311             l2MeasDlIpThruput->burstStartTime = glblTtiCnt;
1312             l2MeasDlIpThruput->isBurstAct = TRUE;
1313             l2MeasDlIpThruput->burstEndSduId = 0;
1314          }
1315          else
1316          {  /* This is the case when another burst started before RLC gets the 
1317                l2MeasDlIpThruput->burstEndSduId = 0; */
1318          }
1319       }
1320       else
1321       {  /* Store the burstEndSduId here */
1322          if((l2MeasDlIpThruput->isBurstAct == TRUE) &&
1323                (!l2MeasDlIpThruput->burstEndSduId))
1324          {
1325             l2MeasDlIpThruput->burstEndSduId = 
1326                l2MeasDlIpThruput->outStngSduArr[l2MeasDlIpThruput->lastSduIdx].sduId;
1327          }
1328       }
1329       if(l2MeasDlIpThruput->isBurstAct == TRUE)
1330       {
1331          l2MeasTb = rlcUtlGetCurMeasTb(gCb,rbCb);
1332          /* Get the lChId from index 0, because index 0 is always for DL */
1333          if(l2MeasTb->numLcId >= RLC_MAX_ACTV_DRB) 
1334          {
1335             /* ccpu00143043 */
1336             return;
1337          }
1338          l2MeasTb->sduInfo[l2MeasTb->numLcId].lcId = rbCb->lch.lChId;
1339          /* Copy all the sduIdx from sduInfo to tb sduInfo */
1340          currTbIdx = l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus;
1341          dstContSduLst = &l2MeasTb->sduInfo[l2MeasTb->numLcId];
1342          /* ccpu00143043 */
1343          for(idx = 0; ((idx < contSduLst->numSdus)
1344                   && (currTbIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)) ; idx++)
1345          {
1346             dstContSduLst->sduIdx[currTbIdx++] = contSduLst->sduIdx[idx];
1347          }
1348          l2MeasTb->sduInfo[l2MeasTb->numLcId].numSdus += idx;
1349          l2MeasTb->numLcId++;
1350       }/* End of isBurstAct */
1351    }/* End of if measOn */
1352
1353    /*stopping Task*/
1354    SStopTask(startTime, PID_RLC_DLIP_TPT_BURSTCALC);
1355    return;
1356 }
1357 /**
1358  * @brief
1359  *        This function is used to store locally the sduIdx of the sdu in the 
1360  *        outstanding SDU array
1361  * 
1362  * @b Description:
1363  *        Stores the Sdu Idx in the contained  SDU Array and increments 
1364  *        the num contained  Sdus 
1365  *
1366  *  @param[in]  sduIdx  the Index of the SDU in the outstanding SDU array
1367  *  @param[out] contSduLst This stores the indices of the SDUs 
1368  *
1369  *  @return  Void
1370  */
1371 Void rlcUtlUpdateContainedSduLst(uint8_t sduIdx,RlcContSduLst *contSduLst)
1372 {
1373    if (contSduLst->numSdus < RLC_L2MEAS_MAX_OUTSTNGSDU)
1374    {
1375     contSduLst->sduIdx[contSduLst->numSdus] = sduIdx;
1376     contSduLst->numSdus++;
1377    }
1378     return;
1379 }
1380
1381 /**
1382  * @brief
1383  *        This function is used to store the sduId of the sdu in the 
1384  *        outstanding SDU array
1385  * 
1386  * @b Description:
1387  *        Stores the Sdu Id in the outstanding SDU Array and increments 
1388  *        the num contained  Sdus 
1389  *
1390  *  @param[out] dlIpThPut  The structure in which the outstanding sdus are 
1391  *                         updated
1392  *  @param[in] sduIdx   The Idx at which the sdu ID is stored  
1393  *  @param[in] sduLen   The size if sdu in bytes  
1394  *  @param[in] newIdx   Indicates if the sdu is already present in the 
1395  *                      outstanding array  
1396  *
1397  *  @return  Void
1398  */
1399 Void rlcUtlUpdateOutStandingSduLst
1400 (
1401 RlcL2MeasDlIpTh   *dlIpThPut, 
1402 uint8_t           sduIdx, 
1403 MsgLen            sduLen, 
1404 uint32_t          sduId,
1405 Bool              newIdx
1406 )
1407 {
1408    if (sduIdx < RLC_L2MEAS_MAX_OUTSTNGSDU)
1409    {
1410    if(newIdx == TRUE)
1411    {      
1412      dlIpThPut->outStngSduArr[sduIdx].numTb = 0;
1413    }
1414    dlIpThPut->outStngSduArr[sduIdx].numTb++;
1415    dlIpThPut->outStngSduArr[sduIdx].sduId = sduId;
1416    dlIpThPut->outStngSduArr[sduIdx].sduLen = sduLen;
1417    }
1418    return;
1419 }
1420 RlcL2MeasTb * rlcUtlGetCurMeasTb(RlcCb *gCb,RlcDlRbCb *rbCb)
1421 {
1422    RlcL2MeasTb  *curL2MeasTb;
1423    uint16_t         idx;
1424
1425    if((curL2MeasTb = rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx]) == NULLP)
1426       {
1427          /* Intentionally avoiding the RLC_ALLOC macro to avoid  memset */
1428          if (SGetSBuf(gCb->init.region,
1429                   gCb->init.pool,
1430                   (Data **)&curL2MeasTb,
1431                   (Size)sizeof(RlcL2MeasTb)) != ROK)
1432          {
1433             return (NULLP);
1434          }
1435          rbCb->ueCb->l2MeasTbCb[rbCb->ueCb->tbIdx] = curL2MeasTb;
1436          /* Initialize the Meas Tb details */
1437          curL2MeasTb->numLcId = 0;
1438          curL2MeasTb->numLchInfo = 0;
1439          curL2MeasTb->txSegSduCnt = 0;
1440          for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1441          {
1442             curL2MeasTb->sduInfo[idx].numSdus = 0;
1443          }
1444          for (idx = 0; idx < RLC_MAX_ACTV_DRB; idx++)
1445          {
1446             curL2MeasTb->lchInfo[idx].numSdus = 0;
1447          }
1448       }
1449    return (curL2MeasTb);
1450 }
1451
1452
1453 /**
1454  *
1455  * @brief Handler for Processing harq status indication
1456  *
1457  *
1458  * @b Description
1459  *        This function is called when the MAC sends a harq ind Mesage.
1460  *        This is used only for UuLoss and Dl Delay and DL Ipthoughput
1461  *        L2 Measurements.
1462  *
1463  *  @param[in] staInd Harq status indication received from MAC.
1464  *  @param[in] ueCb   UeCb corresponding to the Tb Id.
1465  *  @param[in] tbIdx  TB index, 0 for SISO and 0,1 for MIMO.
1466  *
1467  *
1468  *  @return  S16
1469  *      -# ROK
1470  */
1471
1472 S16 rlcUtlProcHarqInd
1473 (
1474 RlcCb            *gCb,
1475 RguHarqStatusInd *hqStaInd,
1476 RlcDlUeCb        *ueCb,
1477 uint8_t          tbIdx
1478 )
1479 {
1480 #ifdef LTE_L2_MEAS
1481    RlcDlRbCb        *rlcRbCb;           /* KW Control Block */
1482    RlcL2MeasTb       *l2MeasTb = NULLP;         /* Measurement TbCb */
1483    uint8_t           lcIdx;             /* Logical channel id index */
1484    uint8_t           sduIndx;            /* sdu index to out standing sdu list in rbCb */
1485    uint32_t          numSdus;           /* number of sdus in the outstanding sdu list */
1486    RlcOutStngSduInfo *outStngSduArr;  /* Outstanding sdu list */
1487    Ticks             ackTime;
1488    Ticks             delay;
1489    uint32_t          totlSduCnt = 0;
1490 #endif
1491    uint8_t           timeAddedFlag;
1492    S16               ret;
1493    volatile uint32_t     startTime = 0;
1494    /*kw005.201 Code added for DL IP thruput measurement*/
1495
1496    /*starting Task*/
1497    SStartTask(&startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1498
1499    ret = ROK;
1500    if(hqStaInd->tbId[tbIdx] >= RLC_INVALID_TBID)
1501    {
1502       return ROK;
1503    }
1504
1505    /* Find the L2 measurement tbCb to process DL Ip thruput*/
1506    l2MeasTb = ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]];
1507    if(l2MeasTb == NULLP)
1508    {
1509       return ROK;
1510    }
1511    /* For each logical channel in the tbCb, process 
1512     * and get the DL IP thruput */
1513    ackTime = SGetTtiCount();
1514    for(lcIdx = 0; ((lcIdx < l2MeasTb->numLcId) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1515    {
1516       timeAddedFlag = FALSE;
1517       if((rlcRbCb = ueCb->lCh[l2MeasTb->sduInfo[lcIdx].lcId - 1].dlRbCb)
1518             == NULLP)
1519       {
1520          continue;
1521       }
1522       /* fix for DL IP stop*/
1523       if (!gCb->u.dlCb->rlcL2Cb.measOn[rlcRbCb->qci]
1524             || (rlcRbCb->rlcId.rbType == CM_LTE_SRB))
1525       {
1526          continue;
1527       }
1528       
1529       /* Get the outstanding SDUs using sdu index stored in Container sduList
1530        * and check for HARQ ACK/NACK */
1531       numSdus = l2MeasTb->sduInfo[lcIdx].numSdus;
1532       /* ccpu00143043 */
1533       if ((numSdus >= RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1534       {
1535          break;
1536       }
1537       totlSduCnt += numSdus;
1538
1539       if (RLC_MEAS_IS_DL_IP_MEAS_ON_FOR_RB(gCb,rlcRbCb))
1540       {
1541          for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1542          {
1543             outStngSduArr =&(rlcRbCb->l2MeasIpThruput.dlIpTh.outStngSduArr[\
1544                   l2MeasTb->sduInfo[lcIdx].sduIdx[sduIndx]]);
1545             if(hqStaInd->status[tbIdx] == TRUE)
1546             {
1547                /* If ACK is for burst End Sdu Id set burstActive 
1548                 * to FALSE  and accumulate time */
1549                if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId == 
1550                         outStngSduArr->sduId) && (outStngSduArr->numTb == 1))
1551                {
1552                   rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1553                   /*Update the l2Sts structure for calculating throughput*/
1554                   rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1555                      += outStngSduArr->sduLen;
1556
1557                   rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1558                      += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1559                   outStngSduArr->sduId = 0;
1560                   outStngSduArr->sduLen = 0;
1561                   outStngSduArr->numTb = 0;
1562                   rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1563                }
1564
1565                /* If burst is active and this sdu is only transmitted in single TB then
1566                 * accumulate volume  and clear the outstanding sduList */
1567                if((rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE) &&
1568                      (--(outStngSduArr->numTb) == 0))
1569                {
1570                   rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.volSummation
1571                      += outStngSduArr->sduLen;
1572
1573                   if(timeAddedFlag == FALSE)
1574                   {
1575                      rlcRbCb->rbL2Cb.l2Sts[RLC_L2MEAS_DL_IP]->dlIpThruput.timeSummation
1576                         += glblTtiCnt - rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime;
1577                      rlcRbCb->l2MeasIpThruput.dlIpTh.burstStartTime = glblTtiCnt;
1578                      timeAddedFlag = TRUE;
1579                   }
1580                   outStngSduArr->sduId = 0;
1581                   outStngSduArr->sduLen = 0;
1582                }
1583             }/* End of status == TRUE */
1584             else
1585             {
1586                if(rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct == TRUE)
1587                {
1588                   if((rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId == 
1589                            outStngSduArr->sduId))
1590                   {
1591                      rlcRbCb->l2MeasIpThruput.dlIpTh.isBurstAct = FALSE;
1592                      rlcRbCb->l2MeasIpThruput.dlIpTh.burstEndSduId = 0;
1593                   }
1594                   /* Clear the outstanding sdu list */
1595                   outStngSduArr->sduId = 0;
1596                   outStngSduArr->sduLen = 0;
1597                   outStngSduArr->numTb = 0;
1598                }
1599             }
1600          }
1601       } 
1602    }
1603
1604    for(lcIdx = 0; ((lcIdx < l2MeasTb->numLchInfo) && (lcIdx < RLC_MAX_ACTV_DRB)); lcIdx++)
1605    {
1606       if((rlcRbCb = ueCb->lCh[l2MeasTb->lchInfo[lcIdx].lcId - 1].dlRbCb)
1607             == NULLP)
1608       {
1609          continue;
1610       }
1611       numSdus = l2MeasTb->lchInfo[lcIdx].numSdus;
1612       if ( numSdus == 0 )
1613       {
1614          continue;
1615       }
1616       /* ccpu00143043 */
1617       if ((numSdus > RLC_L2MEAS_MAX_OUTSTNGSDU) || (numSdus == 0))
1618       {
1619          break;
1620       }
1621       /* Update stats */
1622       if(hqStaInd->status[tbIdx] == TRUE)
1623       {
1624          for(sduIndx = 0; sduIndx < numSdus; sduIndx++)
1625          {
1626             delay = RLC_TIME_DIFF(ackTime,l2MeasTb->lchInfo[lcIdx].sduInfo[sduIndx].arvlTime);
1627             RLC_UPD_PDCP_L2_DLDELAY_STS(gCb,rlcRbCb, delay); 
1628          }
1629          /* Case of sduInfo not updated */
1630          if (totlSduCnt == 0)
1631          {
1632             totlSduCnt = numSdus;
1633          }
1634          RLC_UPD_L2_UU_LOSS_POS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1635       }
1636       else
1637       {
1638          /* Case of sduInfo not updated */
1639          if (totlSduCnt == 0)
1640          {
1641             totlSduCnt = numSdus;
1642          }
1643          RLC_UPD_L2_UU_LOSS_PKTS(gCb,rlcRbCb, (totlSduCnt + l2MeasTb->txSegSduCnt));
1644       }
1645    }
1646    /* Free this tb, deallocate the memory */
1647    RLC_FREE(gCb, l2MeasTb, sizeof(RlcL2MeasTb));
1648    ueCb->l2MeasTbCb[hqStaInd->tbId[tbIdx]] = NULLP;
1649    
1650    /*stopping Task*/
1651    SStopTask(startTime, PID_RLC_DLIP_TPT_PRCHARQIND);
1652
1653    return (ret);
1654 }/* end of  rlcUtlProcHarqInd */ 
1655
1656 /**
1657  *
1658  * @brief Handler for Sending L2 Measurement confirm.
1659  *
1660  *
1661  * @b Description
1662  *        This function sends a consolidates the mesaurements taken during
1663  *        this time and sends the confirm .
1664  *
1665  *  @param[in] measEvtCb    Measurement Event Control Block.
1666  *
1667  *
1668  *  @return  S16
1669  *      -# ROK
1670  */
1671
1672 S16 rlcUtlSndDlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
1673 {
1674    uint32_t         qciIdx;
1675    RlcL2MeasCb      *measCb = NULLP;
1676    RlcL2MeasCfmEvt   measCfmEvt;
1677    uint32_t          posPkts;
1678    uint32_t          dLoss;
1679    uint64_t          dlDataVol;
1680    uint64_t          dlTime;
1681    uint16_t          cntr;
1682    /* Discard new changes starts */
1683    uint8_t           qci = 0;
1684    uint32_t          cfmIdx =0;
1685    /* Discard new changes ends */
1686
1687    /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
1688 #ifndef ALIGN_64BIT
1689    RLOG1(L_DEBUG,"rlcUtlSndL2MeasCfm(transId(%ld))", measEvtCb->transId);
1690 #else
1691    RLOG1(L_DEBUG,"rlcUtlSndL2MeasCfm(transId(%d))", measEvtCb->transId);
1692 #endif
1693
1694    /* Clean up the RB data structures */
1695    measCb = &measEvtCb->measCb;
1696    
1697    memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
1698    measCfmEvt.transId = measEvtCb->transId;
1699
1700    measCfmEvt.measType = measCb->measType;
1701    measCfmEvt.status.status = LCM_PRIM_OK;
1702    measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
1703    
1704    if(measCb->measType & LKW_L2MEAS_DL_IP)
1705    {
1706       RlcL2MeasCbUeMeasInfo *pUeInfoLstCb  = measCb->val.ipThMeas.ueInfoLst;
1707       RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
1708
1709       for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)        
1710       {
1711          pUeInfoLstCfm[cfmIdx].numCfm = 0;
1712          if (pUeInfoLstCb[cntr].isValid == TRUE)
1713          {
1714             pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
1715             pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
1716             for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)           
1717             {
1718                qci = pUeInfoLstCb[cntr].qci[qciIdx];
1719                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
1720
1721                dlDataVol = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation;
1722                dlTime = pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation;
1723
1724                if((0 == dlTime) || !(gCb->u.dlCb->rlcL2Cb.measOn[qci] & LKW_L2MEAS_DL_IP) )
1725                {
1726                   pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 0;
1727                }
1728                else
1729                {
1730                   pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut = 
1731                      (dlDataVol / dlTime);
1732                }
1733                pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.dlIpThPut *= 8;
1734
1735                /* Reset the values after reporting to Application */
1736                pUeInfoLstCb[cntr].measData[qci].dlIpThruput.volSummation = 0;
1737                pUeInfoLstCb[cntr].measData[qci].dlIpThruput.timeSummation = 0;
1738
1739                measCfmEvt.val.ipThMeas.ueInfoLst[cfmIdx].numCfm++;
1740             }
1741             cfmIdx++;
1742          }
1743       }
1744       measCfmEvt.val.ipThMeas.numUes = cfmIdx; 
1745    }
1746    else
1747    {
1748       RlcL2Cntr *pMeasData = measCb->val.nonIpThMeas.measData;
1749       RlcL2MeasCfmNonIpThMeas *pMeasCfmNonIp = &measCfmEvt.val.nonIpThMeas;
1750
1751       pMeasCfmNonIp->numCfm = 0;
1752
1753       for(qciIdx = 0; qciIdx < LKW_MAX_QCI; qciIdx++)
1754       {
1755          qci = measCb->val.nonIpThMeas.qci[qciIdx];
1756          if (qci > 0)
1757          {
1758             pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].qci = qci;
1759
1760             if(measCb->measType & LKW_L2MEAS_UU_LOSS)
1761             {
1762                dLoss = pMeasData[qci].uuLoss.dLoss;
1763                posPkts = pMeasData[qci].uuLoss.posPkts;
1764                if(((posPkts + dLoss) != 0))
1765                {
1766                   pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.uuLoss  =
1767                      ((dLoss  * 1000000) / (posPkts + dLoss));
1768                }
1769                pMeasData[qci].uuLoss.dLoss = 0;
1770                pMeasData[qci].uuLoss.posPkts = 0;
1771             }
1772             if(measCb->measType & LKW_L2MEAS_DL_DISC)
1773             {
1774
1775                pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 0;
1776                if(pMeasData[qci].dlDisc.totSdus != 0)
1777                {
1778                   pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlDiscRate = 
1779                      (((pMeasData[qci].dlDisc.discSdus)  * 1000000) / (pMeasData[qci].dlDisc.totSdus));
1780                }
1781
1782                pMeasData[qci].dlDisc.totSdus = 0;
1783                pMeasData[qci].dlDisc.discSdus = 0;
1784             }
1785             if(measCb->measType & LKW_L2MEAS_DL_DELAY)
1786             {
1787                if (pMeasData[qci].dlPjSduDelay.numSdus > 0)
1788                {
1789                   pMeasCfmNonIp->measCfm[pMeasCfmNonIp->numCfm].val.nonIpThrput.dlSduDelay = 
1790                     (pMeasData[qci].dlPjSduDelay.sduDelay / pMeasData[qci].dlPjSduDelay.numSdus);
1791                   pMeasData[qci].dlPjSduDelay.sduDelay = 0;
1792                   pMeasData[qci].dlPjSduDelay.numSdus = 0;
1793                }
1794             }
1795             pMeasCfmNonIp->numCfm++;
1796          }
1797       }
1798    }
1799    /* Fix Klock warning */
1800    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
1801    return ROK;
1802 } /* rlcUtlSndL2MeasCfm */
1803 /**
1804  *
1805  * @brief Handler for Sending Negative confirm .
1806  *
1807  *
1808   @b Description
1809  *        This function is called when the l2 measurement cannot be started
1810  *        This function sends  negative confirm for all the requests
1811  *
1812  *  @param[in] measReqEvt    Measurement Req Structure
1813  *
1814  *
1815  *  @return  S16
1816  *      -# ROK
1817  */
1818
1819 S16 rlcUtlSndDlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
1820 {
1821
1822    RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
1823    return ROK;
1824 } /* kwUtlSndL2MeasNCfm */
1825 /**
1826  *
1827  * @brief Handler for resetting the RB data structures
1828  *
1829  *
1830  * @b Description
1831  *        This function resets the RB data structure after the expiry of 
1832  *        measurement timer.
1833  *
1834  *  @param[in] measCb    Measurement Control Block.
1835  *
1836  *
1837  *  @return  Void
1838  */
1839
1840 Void rlcUtlResetDlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
1841 {
1842    uint32_t           ueIdx;
1843    uint32_t           qciIdx;
1844    RlcDlUeCb      *ueCb = NULL;
1845
1846
1847
1848    if (measCb->measType & LKW_L2MEAS_DL_IP)
1849    {
1850       for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
1851       {           
1852          if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
1853          {
1854             for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
1855             {
1856                if (measType & LKW_L2MEAS_DL_IP)
1857                {
1858                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.volSummation = 0;
1859                   measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].dlIpThruput.timeSummation = 0;
1860                   gCb->u.dlCb->rlcL2Cb.measOn[qciIdx] &= ~measType; 
1861                }
1862             }
1863
1864             if(ROK  != rlcDbmFetchDlUeCb(gCb,measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
1865                      measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
1866             {
1867                continue;
1868             }
1869
1870          }
1871       }
1872    }
1873    else
1874    {
1875       /* for now the only meas should be DL discard in this case */
1876       if (measCb->measType & LKW_L2MEAS_DL_DISC)
1877       {
1878          uint32_t i;
1879          for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
1880          {
1881             uint8_t qciVal = measCb->val.nonIpThMeas.qci[i];
1882
1883             measCb->val.nonIpThMeas.measData[qciVal].dlDisc.discSdus = 0;
1884             measCb->val.nonIpThMeas.measData[qciVal].dlDisc.totSdus  = 0;
1885          }
1886          
1887       }
1888       if (measCb->measType & LKW_L2MEAS_DL_DELAY)
1889       {
1890          uint32_t i;
1891          for(i = 0; i < measCb->val.nonIpThMeas.numQci; i++)
1892          {
1893             uint8_t qciVal = measCb->val.nonIpThMeas.qci[i];
1894
1895             measCb->val.nonIpThMeas.measData[qciVal].dlPjSduDelay.sduDelay = 0;
1896          }
1897       }
1898       measCb->val.nonIpThMeas.numQci = 0;
1899    }
1900 } /* rlcUtlResetDlL2MeasInRlcRb */
1901 #endif
1902
1903 static Void dumpRLCDlRbInformation(RlcDlRbCb* dlRbCb)
1904 {
1905    if(dlRbCb->mode == CM_LTE_MODE_UM)
1906    {
1907       RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
1908                "UM Downlink UEID:%d CELLID:%d Q size = %d",
1909                        dlRbCb->rlcId.ueId,
1910                        dlRbCb->rlcId.cellId,
1911                        (int)dlRbCb->m.umDl.sduQ.count);
1912    }
1913    else if(dlRbCb->mode == CM_LTE_MODE_AM)
1914    {
1915       uint32_t j, numTxPdus=0;
1916       for(j = 0; j <= (RLC_AM_GET_WIN_SZ(dlRbCb->m.amDl.snLen)); j++)
1917       {
1918          RlcTx *txBuf = rlcUtlGetTxBuf(dlRbCb->m.amDl.txBufLst, j);
1919          if(txBuf != NULLP)
1920          {
1921             numTxPdus++;
1922          }
1923       }
1924       RLOG_ARG4(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
1925                "AM Downlink UEID:%d CELLID:%d Sizes SDU Q = %d TX Q = %d ",
1926                        dlRbCb->rlcId.ueId,
1927                        dlRbCb->rlcId.cellId,
1928                        (int)dlRbCb->m.amDl.sduQ.count,
1929                        (int)numTxPdus);
1930       RLOG_ARG3(L_DEBUG,DBG_RBID,dlRbCb->rlcId.rbId,
1931                "AM Downlink UEID:%d CELLID:%d RETX Q= %d",
1932                        dlRbCb->rlcId.ueId,
1933                        dlRbCb->rlcId.cellId,
1934                        (int)dlRbCb->m.amDl.retxLst.count);
1935    }
1936 }
1937
1938 Void DumpRLCDlDebugInformation(Void)
1939 {
1940    RlcCb* dlInst = rlcCb[1]; /* TODO : Check whether DL is 0 or 1 */
1941
1942    RlcDlCb *dlCb = dlInst->u.dlCb;
1943
1944    RlcDlUeCb *ueCb = NULLP; 
1945    RTLIN_DUMP_DEBUG("RLC Information\n");
1946    RTLIN_DUMP_DEBUG("===============\n");
1947    /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
1948    while (ROK == cmHashListGetNext(&dlCb->ueLstCp, 
1949                                    (PTR) ueCb, 
1950                                    (PTR *)&ueCb))
1951    {
1952       uint32_t i;
1953       for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
1954       {
1955          RlcDlRbCb* dlRbCb = ueCb->srbCb[i]; 
1956          if( dlRbCb != NULLP)
1957          {
1958             dumpRLCDlRbInformation(dlRbCb);
1959          }
1960       }
1961       for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
1962       {
1963          RlcDlRbCb* dlRbCb = ueCb->drbCb[i]; 
1964          if( dlRbCb != NULLP)
1965          {
1966             dumpRLCDlRbInformation(dlRbCb);
1967          }
1968       }
1969    }
1970
1971    RlcDlDataToBeFreed* pToBeFreed = &dlCb->toBeFreed;
1972
1973    RTLIN_DUMP_DEBUG("toBeFreed RETX list size = %d\n",(int)pToBeFreed->reTxLst.count);
1974    RTLIN_DUMP_DEBUG("toBeFreed TX list size   = %d\n",(int)pToBeFreed->txLst.count);
1975    RTLIN_DUMP_DEBUG("toBeFreed SDU list size  = %d\n",(int)pToBeFreed->sduLst.count);
1976    RTLIN_DUMP_DEBUG("toBeFreed RB list size   = %d\n",(int)pToBeFreed->rbLst.count);
1977 }
1978
1979 /**
1980  *
1981  * @b Description
1982  *        This function frees downlink memory 
1983  *
1984  *  @param[in] Void
1985  *
1986  *
1987  *  @return  Void
1988  */
1989
1990 void rlcUtlFreeDlMem( Void)
1991 {
1992   rlcUtlFreeDlMemory(RLC_GET_RLCCB(RLC_DL_INST));
1993 }
1994
1995 /**
1996  *
1997  * @b Description
1998  *        This function returns current time
1999  *
2000  *  @param[in] uint32_t 
2001  *
2002  *
2003  *  @return  Void
2004  */
2005
2006 void rlcUtlGetCurrTime(uint32_t  *currTime)
2007 {
2008    /* Need t define else part for PAL */
2009    *currTime = SGetTtiCount();
2010 }
2011
2012 #if defined(MAC_RLC_HARQ_STA_RBUF) || defined (SS_RBUF)
2013 #ifdef LTE_L2_MEAS
2014 void rlcUtlDlBatchProcHqStaInd( Void)
2015 {
2016    /* Read from Ring Buffer and process PDCP packets */
2017    //Pst pst = {0};
2018
2019    Void *elmIndx = NULLP;
2020    RguHarqStaInd *staInd = NULLP;
2021
2022 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2023    isDatReqProcessed = TRUE;
2024 #endif
2025    elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ);
2026    while(NULLP != elmIndx)
2027    {
2028       staInd = (RguHarqStaInd *)elmIndx;
2029       RlcLiRguHqStaInd(&(staInd->pst), 0, &(staInd->hqStatusInd));
2030
2031       elmIndx = NULLP;
2032       staInd  = NULLP;
2033       SRngIncrRIndx(SS_RNG_BUF_MAC_HARQ);
2034
2035       if((elmIndx = (Void *)SRngGetRIndx(SS_RNG_BUF_MAC_HARQ)) == NULLP)
2036       {
2037 #if defined(MAC_RLC_HARQ_STA_RBUF) && defined(LTE_L2_MEAS)
2038          isDatReqProcessed = FALSE;
2039 #endif
2040          break;
2041       }
2042    }
2043 }
2044 #endif
2045 #endif
2046
2047 /**
2048  * @brief evaluate and trigger PDB based flow control to PDCP 
2049  *
2050  * @details 
2051  *
2052  * @param[in]   rbCb  RB control block 
2053  *
2054  *
2055  *  @return  Void
2056  *
2057  */
2058 Void rlcUtlTrigPdbFlowCntrl(RlcCb  *gCb,RlcDlRbCb *rbCb,uint32_t pktAdmitCnt)
2059 {
2060    KwuFlowCntrlIndInfo    *flowCntrlInfo;
2061    RlcKwuSapCb*            rlckwuSap;
2062
2063    rlckwuSap = gCb->u.dlCb->rlcKwuDlSap + RLC_UI_PDCP;
2064
2065    RLC_SHRABL_STATIC_BUF_ALLOC(rlckwuSap->pst.region, 
2066                               rlckwuSap->pst.pool, 
2067                               flowCntrlInfo, 
2068                               sizeof(KwuFlowCntrlIndInfo));
2069    flowCntrlInfo->rlcId       = rbCb->rlcId;
2070    flowCntrlInfo->pktAdmitCnt = pktAdmitCnt;
2071    RlcUiKwuFlowCntrlInd(&rlckwuSap->pst, rlckwuSap->suId, flowCntrlInfo);
2072 }
2073
2074 /**
2075  *
2076  * @brief Store the DL buffer in hashList  
2077  *
2078  *
2079  * @b Description
2080  *
2081  *   Use the SN % binSize as key and store the received UL buffer
2082  *  @param[in] txBufLst       List CP array
2083  *  @param[in] txBuf          transmitted buffer
2084  *  @param[in] sn              sn of the received buffer 
2085  *
2086  *
2087  *  @return  Void
2088  */
2089 void rlcUtlStoreTxBuf(CmLListCp *txBufLst, RlcTx *txBuf, RlcSn sn)
2090 {
2091    uint32_t   hashKey; 
2092
2093    hashKey = (sn % RLC_TX_BUF_BIN_SIZE );
2094    txBuf->sn = sn; 
2095    txBuf->lnk.node = (PTR)txBuf;
2096    cmLListAdd2Tail(&(txBufLst[hashKey]), &txBuf->lnk);
2097
2098    return;
2099 } /* rlcUtlStoreRecBuf */
2100
2101 /**
2102  *
2103  * @brief Retrieve the DL buffer from the list
2104  *
2105  *
2106  * @Description
2107  *
2108  *   Use the SN % binSize as key and retrieve the DL buffer
2109  *  @param[in] txBufLst       List CP array
2110  *  @param[in] sn              sn of the transmitted buffer 
2111  *
2112  *
2113  *  @return  Void
2114  */
2115 RlcTx* rlcUtlGetTxBuf(CmLListCp *txBufLst, RlcSn sn)
2116 {
2117    uint32_t            hashKey; 
2118    CmLListCp           *txBufLstCp;
2119    RlcTx               *txBuf;
2120    CmLList             *node = NULLP;
2121
2122    hashKey = (sn % RLC_TX_BUF_BIN_SIZE ); 
2123  
2124    txBufLstCp = &txBufLst[hashKey];
2125    CM_LLIST_FIRST_NODE(txBufLstCp, node);
2126    while(node)
2127    {
2128       txBuf = (RlcTx *) node->node;
2129       if(txBuf->sn == sn)
2130       {
2131          return (txBuf);
2132       }
2133       CM_LLIST_NEXT_NODE(txBufLstCp, node);
2134    }
2135    return NULLP;
2136 } /* rlcUtlStoreTxBuf */
2137 /**
2138  *
2139  * @brief Delete the DL buffer from the list
2140  *
2141  *
2142  * @Description
2143  *
2144  *   Use the SN % binSize as key and retrieve the DL buffer
2145  *  @param[in] txBufLst       List CP array
2146  *  @param[in] sn              sn of the transmitted bffer 
2147  *
2148  *
2149  *  @return  Void
2150  */
2151 Void rlcUtlDelTxBuf (CmLListCp *txBufLst,RlcTx  *txBuf,RlcCb *gCb)
2152 {
2153    uint32_t            hashKey; 
2154    CmLListCp           *txBufLstCp;
2155
2156    hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE ); 
2157  
2158    txBufLstCp = &txBufLst[hashKey];
2159    //printf("D-sn(%d)\n", txBuf->hdr.sn);
2160    cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2161    RLC_FREE(gCb, txBuf, sizeof(RlcTx));
2162    return;
2163 } /* rlcUtlDelTxBuf */
2164
2165 /**
2166  *
2167  * @brief Remove the DL buffer from the list
2168  *
2169  *
2170  * @Description
2171  *
2172  *   Use the SN % binSize as key and retrieve the DL buffer
2173  *  @param[in] txBufLst       List CP array
2174  *  @param[in] sn              sn of the transmitted bffer 
2175  *
2176  *
2177  *  @return  Void
2178  */
2179 Void rlcUtlRemovTxBuf(CmLListCp *txBufLst,RlcTx  *txBuf,RlcCb *gCb)
2180 {
2181    uint32_t            hashKey; 
2182    CmLListCp           *txBufLstCp;
2183
2184    hashKey = (txBuf->sn % RLC_TX_BUF_BIN_SIZE ); 
2185  
2186    txBufLstCp = &txBufLst[hashKey];
2187    //printf("D-sn(%d)\n", txBuf->hdr.sn);
2188    cmLListDelFrm(txBufLstCp, &txBuf->lnk);
2189    return;
2190 } /* rlcUtlRemovTxBuf */
2191
2192
2193
2194 /********************************************************************30**
2195          End of file
2196 **********************************************************************/