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