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