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