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