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