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