1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /**********************************************************************
25 Desc: Source code for RLC Unacknowledged mode assembly and
26 reassembly.This file contains following functions
31 --rlcUmmReAssembleSdus
36 **********************************************************************/
37 static const char* RLOG_MODULE_NAME="RLC";
38 static int RLOG_MODULE_ID=2048;
39 static int RLOG_FILE_ID=240;
43 * @brief RLC Unacknowledged Mode uplink module
46 /* header (.h) include files */
47 #include "common_def.h"
48 #include "ckw.h" /* RRC layer */
49 #include "lkw.h" /* RRC layer */
50 #include "kwu.h" /* RLC service user */
51 #include "lkw.h" /* LM Interface */
52 #include "rgu.h" /* MAC layer */
53 #include "kw_env.h" /* RLC environment options */
55 #include "kw.h" /* RLC layer */
60 /* header/extern include files (.x) */
62 #include "ckw.x" /* RRC layer */
63 #include "kwu.x" /* RLC service user */
64 #include "lkw.x" /* LM Interface */
65 #include "rgu.x" /* MAC later */
67 #include "kw.x" /* RLC layer */
70 #define RLC_MODULE (RLC_DBGMASK_UM | RLC_DBGMASK_UL)
72 PRIVATE S16 rlcUmmExtractHdr ARGS ((RlcCb *gCb,
77 PRIVATE Void rlcUmmReAssembleSdus ARGS ((RlcCb *gCb,
79 RlcUmRecBuf *umRecBuf));
83 extern U32 isMemThreshReached(Region region);
87 * @brief Finds and sets the next VR(UR) depending on the
88 * passed sequence number
91 * Finds the next VR(UR) depending on the passed SN. Updates VR(UR) to
92 * the SN of the first UMD PDU with SN >= _nextSn that has not been received
94 * @param[in] umUl pointer to Um mode uplink control block
95 * @param[in] nextSn Sequence number after which the VR(UR) is to set to
99 PRIVATE Void rlcUmmFindNextVRUR (RlcUmUl* umUl, RlcSn nextSn)
101 RlcSn ur = RLC_UM_GET_VALUE(umUl->vrUr, *umUl);
103 RlcSn nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
105 while (ur < nextSnToCompare)
107 if (!(umUl->recBuf[nextSn])) /* if the buffer is empty, SN not received */
112 nextSn = (nextSn + 1) & umUl->modBitMask;
113 nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
118 * @brief Checks whether a sequence number is within the
119 * re-ordering window or not
121 * @param[in] sn Sequence Number to be checked
122 * @param[in] umUl pointer to Um mode uplink control block
130 PRIVATE S16 rlcUmmCheckSnInReordWindow (RlcSn sn,
131 CONSTANT RlcUmUl* CONSTANT umUl)
133 return (RLC_UM_GET_VALUE(sn, *umUl) < RLC_UM_GET_VALUE(umUl->vrUh, *umUl));
137 * @brief Handler to process the Data Indication from the lower layer
138 * and send the PDUs to re-assembly unit.
141 * This function processes the PDUs received from the lower layer
142 * re-orders them and sends them one after the other in sequence
143 * to the re-assembly unit.
145 * @param[in] gCb RLC Instance control block
146 * @param[in] rbCb RB control block
147 * @param[in] pduInfo Pdu information
151 /* kw005.201 added support for L2 Measurement */
155 Void rlcUmmProcessPdus
158 RlcUlRbCb *rbCb, /* Rb Control Block */
159 KwPduInfo *pduInfo, /* Pdu data and related information */
160 U32 ttiCnt /* ttiCnt received from MAC */
163 Void rlcUmmProcessPdus(rbCb,pduInfo,ttiCnt)
165 RlcUlRbCb *rbCb; /* Rb Control Block */
166 KwPduInfo *pduInfo; /* Pdu data and related information */
167 U32 ttiCnt; /* ttiCnt received from MAC */
171 Void rlcUmmProcessPdus
174 RlcUlRbCb *rbCb, /* Rb Control Block */
175 KwPduInfo *pduInfo /* Pdu data and related information */
178 Void rlcUmmProcessPdus(rbCb,pduInfo)
180 RlcUlRbCb *rbCb; /* Rb Control Block */
181 KwPduInfo *pduInfo; /* Pdu data and related information */
185 RlcSn *vrUh; /* vr(uh) */
186 RlcSn *vrUr; /* vr(ur) */
187 RlcSn *vrUx; /* vr(ux) */
188 U16 curSn; /* Current Sequence Number */
189 U32 pduCount; /* PDU count */
190 U32 count; /* Loop counter */
191 RlcUmRecBuf **recBuf; /* UM Reception Buffer */
193 Bool tmrRunning; /* Boolean for checking Tmr */
194 /* kw005.201 added support for L2 Measurement */
196 TRC2(rlcUmmProcessPdus)
201 /* pduCount should be the min of RGU_MAX_PDU and pduInfo->numPdu */
202 pduCount = (pduInfo->numPdu < RGU_MAX_PDU)? pduInfo->numPdu : RGU_MAX_PDU;
204 vrUh = &(rbCb->m.umUl.vrUh);
205 vrUr = &(rbCb->m.umUl.vrUr);
206 vrUx = &(rbCb->m.umUl.vrUx);
207 recBuf = (rbCb->m.umUl.recBuf);
209 while (count < pduCount)
214 Buffer *pdu = pduInfo->mBuf[count];
215 RlcUmRecBuf *tmpRecBuf;
216 gCb->genSts.pdusRecv++;
217 #ifndef RGL_SPECIFIC_CHANGES
220 extern U32 ulrate_rgu;
222 SFndLenMsg(pdu, &len);
227 /* create a buffer to be later inserted into the reception buffer */
228 RLC_ALLOC_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
229 #if (ERRCLASS & ERRCLS_ADD_RES)
230 if (tmpRecBuf == NULLP)
232 RLOG_ARG2(L_FATAL, DBG_RBID,rbCb->rlcId.rbId,
233 "Memory allocation failed UEID:%d CELLID:%d",
240 #endif /* ERRCLASS & ERRCLS_ADD_RES */
241 /* ccpu00142274 - UL memory based flow control*/
242 #ifndef RGL_SPECIFIC_CHANGES
245 /* Changed the condition to TRUE from ROK */
246 #ifndef XEON_SPECIFIC_CHANGES
247 if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
249 extern U32 rlculdrop;
252 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
253 /*Fix for CR ccpu00144030: If threshhold is hit then also count
254 *should be incrmented */
262 /* get the pdu header */
263 if (rlcUmmExtractHdr(gCb, rbCb, pdu, &(tmpRecBuf->umHdr)))
265 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
266 "Header Extraction Failed UEID:%d CELLID:%d",
270 /* Header extraction is a problem.
271 * log an error and free the allocated memory */
273 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
276 /* kw005.201 ccpu00117318, updating the statistics */
277 gCb->genSts.errorPdusRecv++;
280 curSn = tmpRecBuf->umHdr.sn;
282 /* Check if the PDU should be discarded or not */
283 ur = RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL);
284 uh = RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL);
285 seqNum = RLC_UM_GET_VALUE(curSn, RLC_UMUL);
287 if (((ur < seqNum) && (seqNum < uh) && (RLC_UMUL.recBuf[curSn])) ||
290 /* PDU needs to be discarded */
291 RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
292 "Received a duplicate pdu with sn %d UEID:%d CELLID:%d",
298 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
300 /* kw005.201 ccpu00117318, updating the statistics */
301 gCb->genSts.unexpPdusRecv++;
305 /* kw005.201 added support for L2 Measurement */
308 /* kw006.201 ccpu00120058, reduced code complexity by adding new function */
309 rlcUtlCalUlIpThrPut(gCb,rbCb, pdu, ttiCnt);
313 recBuf[curSn] = tmpRecBuf;
315 recBuf[curSn]->pdu = pdu;
316 SFndLenMsg(pdu,&(recBuf[curSn]->pduSz));
317 /* kw005.201 ccpu00117318, updating the statistics */
318 gCb->genSts.bytesRecv += recBuf[curSn]->pduSz;
320 if (!rlcUmmCheckSnInReordWindow(curSn,&RLC_UMUL))
321 { /* currSn is outside re-ordering window */
322 *vrUh = (curSn + 1) & RLC_UMUL.modBitMask;
324 /* re-assemble all pdus outside the modified re-ordering window */
325 /* the first SN is VR(UR) */
326 if (!rlcUmmCheckSnInReordWindow(*vrUr,&RLC_UMUL))
328 /* TODO : should it be VR(UR) + 1 ?... check, earlier it was so */
329 RlcSn sn = *vrUr; /* SN's which need to be re-assembled */
330 RlcSn lowerEdge; /* to hold the lower-edge of the
331 re-ordering window */
333 /* The new value ov VR(UR) is the lower end of the window i
334 * and SN's still this value need to be re-assembled */
336 *vrUr = (*vrUh - RLC_UMUL.umWinSz) & RLC_UMUL.modBitMask;
337 lowerEdge = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
339 while (RLC_UM_GET_VALUE(sn, RLC_UMUL) < lowerEdge)
343 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
344 RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
347 sn = (sn + 1) & RLC_UMUL.modBitMask;
354 RlcSn tSn = RLC_UM_GET_VALUE(sn,RLC_UMUL);
357 /* set VR(UR) to next SN > current VR(UR) which is not received */
358 RlcSn nextVrUr = (*vrUr + 1) & RLC_UMUL.modBitMask;
359 rlcUmmFindNextVRUR(&RLC_UMUL, nextVrUr);
361 /* re-assemble SDUs with SN < Vr(UR) */
362 tVrUr = RLC_UM_GET_VALUE(*vrUr,RLC_UMUL);
363 while (recBuf[sn] && tSn < tVrUr)
365 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
366 RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
368 sn = (sn + 1) & RLC_UMUL.modBitMask;
369 tSn = RLC_UM_GET_VALUE(sn, RLC_UMUL);
373 tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, RLC_EVT_UMUL_REORD_TMR);
377 RlcSn tVrUx = RLC_UM_GET_VALUE(*vrUx, RLC_UMUL);
378 RlcSn tVrUr = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
380 RlcSn tVrUh = RLC_UM_GET_VALUE(*vrUh, RLC_UMUL);
382 S16 ret = rlcUmmCheckSnInReordWindow(*vrUx, &RLC_UMUL);
384 if ( (tVrUx <= tVrUr) || ((!ret) && (tVrUx != tVrUh)))
386 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
393 if (RLC_UM_GET_VALUE(*vrUh, RLC_UMUL) > RLC_UM_GET_VALUE(*vrUr, RLC_UMUL))
395 rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
400 }/* end while count < pduCount */
402 rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
403 #endif /* LTE_L2_MEAS */
408 * @brief Handler to reassemble the SDUs and send them to the upper layer.
411 * This function processes the received in-sequence PDU and
412 * re-assembles the SDUs and sends them to the upper layer.
414 * @param[in] gCb RLC Instance control block
415 * @param[in] rbCb RB control block
416 * @param[in] umRecBuf Reception Buffer to be Re-Assembled
421 PRIVATE Void rlcUmmReAssembleSdus
425 RlcUmRecBuf *umRecBuf
428 PRIVATE Void rlcUmmReAssembleSdus(gCb,rbCb,umRecBuf)
431 RlcUmRecBuf *umRecBuf;
434 U32 liCount; /* LI count */
435 U32 count; /* Loop counter */
436 U8 fi; /* Framing Info */
437 U16 sn; /* Sequence Number of current PDU */
438 MsgLen len; /* PDU Length */
439 Buffer *sdu; /* SDU to be sent to upper layer */
440 Buffer *remPdu; /* Remaining PDU */
441 Buffer **partialSdu; /* Partial SDU */
443 TRC2(rlcUmmReAssembleSdus)
446 liCount = umRecBuf->umHdr.numLi;
447 fi = umRecBuf->umHdr.fi;
448 sn = umRecBuf->umHdr.sn;
450 for (count = 0; (count <= liCount);count++)
452 if (count < liCount )
453 len = umRecBuf->umHdr.li[count];
456 if (!(umRecBuf->pdu))
460 SFndLenMsg(umRecBuf->pdu,&len);
463 /* get the sdu out of the pdu */
464 SSegMsg(umRecBuf->pdu,len,&remPdu);
466 umRecBuf->pdu = remPdu;
468 partialSdu = &(rbCb->m.umUl.partialSdu);
469 /* While re-assembling the SDUs, consider the first LI and perform
470 * the following steps.
471 -# If the first bit of FI(Framing Info of 2 bits) is set =>
472 -# The current Data field in the PDU is a segment.
473 So form a SDU only if the
474 rbCb->m.um.umUl.partialSdu exists and the SNs are
476 -# If there are no LIs and the second bit of LI is 1
477 then a partial SDU is formed which would not be sent
480 -# If rbCb->partialSdu is not NULL then flush it off.
481 -# If LI count > 0 or LI count is 0 and second bit
483 The SDU is complete.So send it to upper layer.
485 The SDU is partial and is placed
486 in rbCb->m.um.umUl.partialSdu;
494 (sn == ((rbCb->m.umUl.sn + 1) & rbCb->m.umUl.modBitMask)))
496 SCatMsg(*partialSdu,sdu,M1M2);
498 if (liCount > 0 || !(fi & 1))
500 rlcUtlSndDatInd(gCb,rbCb,*partialSdu);
506 /* Partial Sdu stored is not valid now.So free it */
509 RLC_FREE_BUF(*partialSdu);
521 RLC_FREE_BUF(*partialSdu); /* RLC mem leak fix */
525 if (liCount > 0 || !( fi & 1))
527 rlcUtlSndDatInd(gCb,rbCb,sdu);
536 If the SDU pointer has the last Data field of the PDU
537 -# If FI is 1,place the SDU in rbCb->m.um.umDl.partialSdu
538 -# else send the SDU to upper layer.
540 else if (count == liCount)
548 rlcUtlSndDatInd(gCb, rbCb, sdu);
552 If the LI is something other than the first one,
553 just send the SDU to the upper layer */
556 rlcUtlSndDatInd(gCb, rbCb, sdu);
559 rbCb->m.umUl.sn = sn;
565 * @brief Handler to process the re-establishment request received
566 * from the upper layer.
569 * This function does the following functions :
570 * - If direction of the RB is downlink :
571 * Remove all the SDUs in the SDU queue.
572 * - If direction of the RB is uplink :
573 * Call rlcUmmReAssembleSdus() for each PDU with SN < VR(UH)
575 * @param[in] gCb RLC Instance control block
576 * @param[in] rlcID Identity of the RLC entity for which
577 * re-establishment is to be done
578 * @param[in] rbCb RB control block for which re-establishment
584 Void rlcUmmUlReEstablish
591 Void rlcUmmUlReEstablish(gCb, rlcId, rbCb)
599 RlcUmRecBuf **recBuf; /* UM Reception Buffer */
600 RlcKwuSapCb *rlcKwSap; /* KWU SAP Information */
602 TRC2(rlcUmmUlReEstablish)
605 curSn = rbCb->m.umUl.vrUr;
606 vrUh = RLC_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
607 recBuf = rbCb->m.umUl.recBuf;
609 if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
611 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
614 while (RLC_UM_GET_VALUE(curSn,rbCb->m.umUl) < vrUh)
616 if ( recBuf[curSn] != NULLP )
618 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[curSn]);
619 RLC_FREE_WC(gCb,recBuf[curSn],sizeof(RlcUmRecBuf));
620 recBuf[curSn] = NULLP;
622 curSn = (curSn + 1) & rbCb->m.umUl.modBitMask;
624 rbCb->m.umUl.vrUr = 0;
625 rbCb->m.umUl.vrUh = 0;
626 rbCb->m.umUl.vrUx = 0;
628 rlcKwSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
630 /* In the UM Mode always send reestablish-indication to Upper Latyer*/
631 RlcUiKwuReEstCmpInd(&rlcKwSap->pst, rlcKwSap->suId, *rlcId);
637 * @brief Handler to extract the header from a PDU
640 * This function is used to extract the header of a PDU and store it
641 * along with the PDU buffer.The sequence number,framing info
642 * and LIs are extracted by this function.
644 * @param[in] gCb RLC Instance control block
645 * @param[in] rbCb Rb Control block for which the pdu is received
646 * @param[in] pdu PDU buffer
647 * @param[out] umHdr UM header to be filled after extraction
654 PRIVATE S16 rlcUmmExtractHdr
662 PRIVATE S16 rlcUmmExtractHdr(gCb, rbCb, pdu, umHdr)
669 U8 e; /* Extension Bit */
670 Data dst[2]; /* Destination Buffer */
671 S32 totalSz; /* Sum of LIs */
672 MsgLen pduSz; /* PDU size */
673 #if (ERRCLASS & ERRCLS_DEBUG)
674 S16 ret; /* Return Value */
677 TRC3(rlcUmmExtractHdr)
680 SFndLenMsg(pdu,&pduSz);
682 if ( rbCb->m.umUl.snLen == 1)
684 #if (ERRCLASS & ERRCLS_DEBUG)
685 ret = SRemPreMsg(dst,pdu);
688 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
689 "SRemPreMsg Failed for 5 bit SN UEID:%d CELLID:%d",
699 umHdr->sn = (dst[0]) & 0x1F;
700 umHdr->fi = (dst[0]) >> 6;
701 e = (dst[0]>>5) & 0x01;
705 /* snLen - sequnce length will be 10 bits requiring 2 bytes */
706 #if (ERRCLASS & ERRCLS_DEBUG)
707 ret = SRemPreMsgMult(dst,2,pdu);
710 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
711 "SRemPreMsgMult Failed for 10 bits SN UEID:%d CELLID:%d",
717 SRemPreMsgMult(dst,2,pdu);
721 /* kw005.201 R9 Upgrade 3gpp spec 36.322 ver9.3.0 CR0082 *
722 * Removed the "if" condition for checking the reserved field *
723 * Added mask 0x03 for extracting the FI field. */
725 umHdr->fi = ( (dst[0] ) >> 3) & 0x03;
726 e = ( (dst[0] ) >> 2) & 0x01;
727 umHdr->sn = ( dst[0] & 0x03) << 8;
734 while(e && umHdr->numLi < RLC_MAX_UL_LI )
736 #if (ERRCLASS & ERRCLS_DEBUG)
737 ret = SRemPreMsgMult(dst,2,pdu);
740 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
741 "SRemPreMsgMult Failed UEID:%d CELLID:%d",
747 SRemPreMsgMult(dst,2,pdu);
749 umHdr->li[umHdr->numLi] = ((dst[0]) & 0x7F) << 4;
750 umHdr->li[umHdr->numLi] |= dst[1] >> 4;
751 if ( 0 == umHdr->li[umHdr->numLi] )
753 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
754 "Received LI as 0 UEID:%d CELLID:%d",
759 totalSz += umHdr->li[umHdr->numLi];
760 if ( pduSz <= totalSz )
762 RLOG_ARG3(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
763 "SN [%d]: UEID:%d CELLID:%d",
767 RLOG_ARG4(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
768 "Corrupted PDU as TotSz[%lu] PduSz[%lu] UEID:%d CELLID:%d ",
773 return RFAILED; /* the situation where in the PDU size
774 is something that does not match with
780 e = ((dst[0]) & 0x80) >> 7;
782 if ( e && umHdr->numLi < RLC_MAX_UL_LI)
784 U8 tmp = ((dst[1]) & 0x08) >> 3;
785 umHdr->li[umHdr->numLi] = ( dst[1] & 0x07) << 8;
788 #if (ERRCLASS & ERRCLS_DEBUG)
789 ret = SRemPreMsg(dst,pdu);
792 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
793 "SRemPreMsg Failed UEID:%d CELLID:%d",
801 umHdr->li[umHdr->numLi] |= ( dst[0] ); /* The first byte lies in
802 the first 8 bits.We want
803 them in the last 8 bits */
804 if ( 0 == umHdr->li[umHdr->numLi] )
806 RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
807 "Received LI as 0 UEID:%d CELLID:%d",
812 totalSz += umHdr->li[umHdr->numLi];
818 return RFAILED; /* the situation where in the PDU size is
819 something that does not match with the
825 } /* while(e && umHdr->numLi < RLC_MAX_LI ) */
828 /* PDU was constructed with LIs that exceeded RLC_MAX_LI */
835 * @brief Handles expiry of re-ordering timer
837 * @param[in] gCb RLC Instance control block
838 * @param[in] rbCb Rb Control block for which re-order timer expired
843 Void rlcUmmReOrdTmrExp
849 Void rlcUmmReOrdTmrExp(gCb, rbCb)
854 RlcSn prevVrUr; /* prevVrUr */
856 TRC3(rlcUmmReOrdTmrExp)
859 prevVrUr = RLC_UMUL.vrUr;
861 /* set VR(UR) to SN >= VR(UX) that has not been received */
862 rlcUmmFindNextVRUR(&RLC_UMUL, RLC_UMUL.vrUx);
864 while (RLC_UM_GET_VALUE(prevVrUr,RLC_UMUL) <
865 RLC_UM_GET_VALUE(RLC_UMUL.vrUr,RLC_UMUL))
867 if (RLC_UMUL.recBuf[prevVrUr])
869 rlcUmmReAssembleSdus(gCb, rbCb, RLC_UMUL.recBuf[prevVrUr]);
870 if(RLC_UMUL.recBuf[prevVrUr]->pdu != NULLP) /* RLC mem leak fix */
872 RLC_FREE_BUF(RLC_UMUL.recBuf[prevVrUr]->pdu);
874 RLC_FREE_WC(gCb, RLC_UMUL.recBuf[prevVrUr], sizeof(RlcUmRecBuf));
875 RLC_UMUL.recBuf[prevVrUr] = NULLP;
878 prevVrUr = (prevVrUr + 1) & rbCb->m.umUl.modBitMask;
881 if (RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL) >
882 RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL))
884 rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
885 RLC_UMUL.vrUx = RLC_UMUL.vrUh;
891 * Function to release/free the UnAcknowledged Mode Module RbCb buffers
894 * This primitive Frees the UM RbCb transmission Buffer, retransmission
895 * Buffer and reciption Buffers
897 * @param [in] gCb - RLC instance Control Block
898 * @param [in] rbCb - RB Control Block
904 Void rlcUmmFreeUlRbCb
910 Void rlcUmmFreeUlRbCb(gCb,rbCb)
915 RlcSn curSn = 0; /* sequence number of PDU */
916 RlcSn windSz; /* PDU window size */
917 RlcUmRecBuf **umRecBuf; /* UM module receive buffer */
919 TRC2(rlcUmmFreeUlRbCb)
922 windSz = rbCb->m.umUl.umWinSz << 1;
924 umRecBuf = rbCb->m.umUl.recBuf;
926 if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
928 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
930 while (curSn < windSz)
932 if (umRecBuf[curSn] != NULLP)
934 RLC_FREE_BUF_WC(umRecBuf[curSn]->pdu);
935 umRecBuf[curSn]->pdu = NULLP;
937 RLC_FREE_WC(gCb, umRecBuf[curSn], sizeof(RlcUmRecBuf));
938 umRecBuf[curSn] = NULLP;
942 RLC_FREE_WC(gCb,rbCb->m.umUl.recBuf, (windSz ) * sizeof(RlcUmRecBuf*));
943 rbCb->m.umUl.recBuf = NULLP;
948 /********************************************************************30**
950 **********************************************************************/