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