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