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