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 **********************************************************************/
39 * @brief RLC Unacknowledged Mode uplink module
42 /* header (.h) include files */
43 #include "common_def.h"
44 #include "ckw.h" /* RRC layer */
45 #include "lkw.h" /* RRC layer */
46 #include "kwu.h" /* RLC service user */
47 #include "lkw.h" /* LM Interface */
48 #include "rgu.h" /* MAC layer */
49 #include "kw_env.h" /* RLC environment options */
51 #include "kw.h" /* RLC layer */
56 /* header/extern include files (.x) */
58 #include "ckw.x" /* RRC layer */
59 #include "kwu.x" /* RLC service user */
60 #include "lkw.x" /* LM Interface */
61 #include "rgu.x" /* MAC later */
63 #include "kw.x" /* RLC layer */
66 #define RLC_MODULE (RLC_DBGMASK_UM | RLC_DBGMASK_UL)
68 uint8_t rlcUmmExtractHdr ARGS ((RlcCb *gCb,
73 void rlcUmmReAssembleSdus ARGS ((RlcCb *gCb,
75 RlcUmRecBuf *umRecBuf));
79 extern U32 isMemThreshReached(Region region);
83 * @brief Finds and sets the next VR(UR) depending on the
84 * passed sequence number
87 * Finds the next VR(UR) depending on the passed SN. Updates VR(UR) to
88 * the SN of the first UMD PDU with SN >= _nextSn that has not been received
90 * @param[in] umUl pointer to Um mode uplink control block
91 * @param[in] nextSn Sequence number after which the VR(UR) is to set to
95 void rlcUmmFindNextVRUR (RlcUmUl* umUl, RlcSn nextSn)
97 RlcSn ur = RLC_UM_GET_VALUE(umUl->vrUr, *umUl);
99 RlcSn nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
101 while (ur < nextSnToCompare)
103 if (!(umUl->recBuf[nextSn])) /* if the buffer is empty, SN not received */
108 nextSn = (nextSn + 1) & umUl->modBitMask;
109 nextSnToCompare = RLC_UM_GET_VALUE(nextSn,*umUl);
114 * @brief Checks whether a sequence number is within the
115 * re-ordering window or not
117 * @param[in] sn Sequence Number to be checked
118 * @param[in] umUl pointer to Um mode uplink control block
126 int16_t rlcUmmCheckSnInReordWindow (RlcSn sn, CONSTANT RlcUmUl* CONSTANT umUl)
128 return (RLC_UM_GET_VALUE(sn, *umUl) < RLC_UM_GET_VALUE(umUl->vrUh, *umUl));
132 * @brief Handler to process the Data Indication from the lower layer
133 * and send the PDUs to re-assembly unit.
136 * This function processes the PDUs received from the lower layer
137 * re-orders them and sends them one after the other in sequence
138 * to the re-assembly unit.
140 * @param[in] gCb RLC Instance control block
141 * @param[in] rbCb RB control block
142 * @param[in] pduInfo Pdu information
146 /* kw005.201 added support for L2 Measurement */
148 void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo, uint32_t ttiCnt)
150 void rlcUmmProcessPdus(RlcCb *gCb, RlcUlRbCb *rbCb, KwPduInfo *pduInfo)
153 RlcSn *vrUh; /* vr(uh) */
154 RlcSn *vrUr; /* vr(ur) */
155 RlcSn *vrUx; /* vr(ux) */
156 uint16_t curSn; /* Current Sequence Number */
157 uint32_t pduCount; /* PDU count */
158 uint32_t count; /* Loop counter */
159 RlcUmRecBuf **recBuf; /* UM Reception Buffer */
161 bool tmrRunning; /* Boolean for checking Tmr */
165 /* pduCount should be the min of RGU_MAX_PDU and pduInfo->numPdu */
166 pduCount = (pduInfo->numPdu < RGU_MAX_PDU)? pduInfo->numPdu : RGU_MAX_PDU;
168 vrUh = &(rbCb->m.umUl.vrUh);
169 vrUr = &(rbCb->m.umUl.vrUr);
170 vrUx = &(rbCb->m.umUl.vrUx);
171 recBuf = (rbCb->m.umUl.recBuf);
173 while (count < pduCount)
178 Buffer *pdu = pduInfo->mBuf[count];
179 RlcUmRecBuf *tmpRecBuf;
180 gCb->genSts.pdusRecv++;
181 #ifndef RGL_SPECIFIC_CHANGES
184 extern uint32_t ulrate_rgu;
186 ODU_GET_MSG_LEN(pdu, &len);
191 /* create a buffer to be later inserted into the reception buffer */
192 RLC_ALLOC_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
193 #if (ERRCLASS & ERRCLS_ADD_RES)
194 if (tmpRecBuf == NULLP)
196 DU_LOG("\nRLC : rlcUmmProcessPdus: Memory allocation failed UEID:%d CELLID:%d",\
197 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
198 ODU_PUT_MSG_BUF(pdu);
201 #endif /* ERRCLASS & ERRCLS_ADD_RES */
202 /* ccpu00142274 - UL memory based flow control*/
203 #ifndef RGL_SPECIFIC_CHANGES
206 /* Changed the condition to TRUE from ROK */
207 #ifndef XEON_SPECIFIC_CHANGES
208 if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
210 extern uint32_t rlculdrop;
213 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
214 /*Fix for CR ccpu00144030: If threshhold is hit then also count
215 *should be incrmented */
223 /* get the pdu header */
224 if (rlcUmmExtractHdr(gCb, rbCb, pdu, &(tmpRecBuf->umHdr)))
226 DU_LOG("\nRLC : rlcUmmProcessPdus: Header Extraction Failed UEID:%d CELLID:%d",\
227 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
229 /* Header extraction is a problem.
230 * log an error and free the allocated memory */
232 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
233 ODU_PUT_MSG_BUF(pdu);
235 /* kw005.201 ccpu00117318, updating the statistics */
236 gCb->genSts.errorPdusRecv++;
239 curSn = tmpRecBuf->umHdr.sn;
241 /* Check if the PDU should be discarded or not */
242 ur = RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL);
243 uh = RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL);
244 seqNum = RLC_UM_GET_VALUE(curSn, RLC_UMUL);
246 if (((ur < seqNum) && (seqNum < uh) && (RLC_UMUL.recBuf[curSn])) ||
249 /* PDU needs to be discarded */
250 DU_LOG("\nRLC : rlcUmmProcessPdus: Received a duplicate pdu with sn %d \
251 UEID:%d CELLID:%d", curSn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
254 RLC_FREE_WC(gCb, tmpRecBuf, sizeof(RlcUmRecBuf));
256 /* kw005.201 ccpu00117318, updating the statistics */
257 gCb->genSts.unexpPdusRecv++;
261 /* kw005.201 added support for L2 Measurement */
264 /* kw006.201 ccpu00120058, reduced code complexity by adding new function */
265 rlcUtlCalUlIpThrPut(gCb,rbCb, pdu, ttiCnt);
269 recBuf[curSn] = tmpRecBuf;
271 recBuf[curSn]->pdu = pdu;
272 ODU_GET_MSG_LEN(pdu,&(recBuf[curSn]->pduSz));
273 /* kw005.201 ccpu00117318, updating the statistics */
274 gCb->genSts.bytesRecv += recBuf[curSn]->pduSz;
276 if (!rlcUmmCheckSnInReordWindow(curSn,&RLC_UMUL))
277 { /* currSn is outside re-ordering window */
278 *vrUh = (curSn + 1) & RLC_UMUL.modBitMask;
280 /* re-assemble all pdus outside the modified re-ordering window */
281 /* the first SN is VR(UR) */
282 if (!rlcUmmCheckSnInReordWindow(*vrUr,&RLC_UMUL))
284 /* TODO : should it be VR(UR) + 1 ?... check, earlier it was so */
285 RlcSn sn = *vrUr; /* SN's which need to be re-assembled */
286 RlcSn lowerEdge; /* to hold the lower-edge of the
287 re-ordering window */
289 /* The new value ov VR(UR) is the lower end of the window i
290 * and SN's still this value need to be re-assembled */
292 *vrUr = (*vrUh - RLC_UMUL.umWinSz) & RLC_UMUL.modBitMask;
293 lowerEdge = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
295 while (RLC_UM_GET_VALUE(sn, RLC_UMUL) < lowerEdge)
299 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
300 RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
303 sn = (sn + 1) & RLC_UMUL.modBitMask;
310 RlcSn tSn = RLC_UM_GET_VALUE(sn,RLC_UMUL);
313 /* set VR(UR) to next SN > current VR(UR) which is not received */
314 RlcSn nextVrUr = (*vrUr + 1) & RLC_UMUL.modBitMask;
315 rlcUmmFindNextVRUR(&RLC_UMUL, nextVrUr);
317 /* re-assemble SDUs with SN < Vr(UR) */
318 tVrUr = RLC_UM_GET_VALUE(*vrUr,RLC_UMUL);
319 while (recBuf[sn] && tSn < tVrUr)
321 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[sn]);
322 RLC_FREE_WC(gCb,recBuf[sn],sizeof(RlcUmRecBuf));
324 sn = (sn + 1) & RLC_UMUL.modBitMask;
325 tSn = RLC_UM_GET_VALUE(sn, RLC_UMUL);
329 tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, RLC_EVT_UMUL_REORD_TMR);
333 RlcSn tVrUx = RLC_UM_GET_VALUE(*vrUx, RLC_UMUL);
334 RlcSn tVrUr = RLC_UM_GET_VALUE(*vrUr ,RLC_UMUL);
336 RlcSn tVrUh = RLC_UM_GET_VALUE(*vrUh, RLC_UMUL);
338 S16 ret = rlcUmmCheckSnInReordWindow(*vrUx, &RLC_UMUL);
340 if ( (tVrUx <= tVrUr) || ((!ret) && (tVrUx != tVrUh)))
342 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
349 if (RLC_UM_GET_VALUE(*vrUh, RLC_UMUL) > RLC_UM_GET_VALUE(*vrUr, RLC_UMUL))
351 rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
356 }/* end while count < pduCount */
358 rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
359 #endif /* LTE_L2_MEAS */
364 * @brief Handler to reassemble the SDUs and send them to the upper layer.
367 * This function processes the received in-sequence PDU and
368 * re-assembles the SDUs and sends them to the upper layer.
370 * @param[in] gCb RLC Instance control block
371 * @param[in] rbCb RB control block
372 * @param[in] umRecBuf Reception Buffer to be Re-Assembled
376 void rlcUmmReAssembleSdus(RlcCb *gCb, RlcUlRbCb *rbCb, RlcUmRecBuf *umRecBuf)
378 uint32_t liCount; /* LI count */
379 uint32_t count; /* Loop counter */
380 uint8_t fi; /* Framing Info */
381 uint16_t sn; /* Sequence Number of current PDU */
382 MsgLen len; /* PDU Length */
383 Buffer *sdu; /* SDU to be sent to upper layer */
384 Buffer *remPdu; /* Remaining PDU */
385 Buffer **partialSdu; /* Partial SDU */
387 liCount = umRecBuf->umHdr.numLi;
388 fi = umRecBuf->umHdr.fi;
389 sn = umRecBuf->umHdr.sn;
391 for (count = 0; (count <= liCount);count++)
393 if (count < liCount )
394 len = umRecBuf->umHdr.li[count];
397 if (!(umRecBuf->pdu))
401 ODU_GET_MSG_LEN(umRecBuf->pdu,&len);
404 /* get the sdu out of the pdu */
405 ODU_SEGMENT_MSG(umRecBuf->pdu,len,&remPdu);
407 umRecBuf->pdu = remPdu;
409 partialSdu = &(rbCb->m.umUl.partialSdu);
410 /* While re-assembling the SDUs, consider the first LI and perform
411 * the following steps.
412 -# If the first bit of FI(Framing Info of 2 bits) is set =>
413 -# The current Data field in the PDU is a segment.
414 So form a SDU only if the
415 rbCb->m.um.umUl.partialSdu exists and the SNs are
417 -# If there are no LIs and the second bit of LI is 1
418 then a partial SDU is formed which would not be sent
421 -# If rbCb->partialSdu is not NULL then flush it off.
422 -# If LI count > 0 or LI count is 0 and second bit
424 The SDU is complete.So send it to upper layer.
426 The SDU is partial and is placed
427 in rbCb->m.um.umUl.partialSdu;
435 (sn == ((rbCb->m.umUl.sn + 1) & rbCb->m.umUl.modBitMask)))
437 ODU_CAT_MSG(*partialSdu,sdu,M1M2);
439 if (liCount > 0 || !(fi & 1))
441 rlcUtlSendUlDataToDu(gCb,rbCb,*partialSdu);
447 /* Partial Sdu stored is not valid now.So free it */
450 RLC_FREE_BUF(*partialSdu);
462 RLC_FREE_BUF(*partialSdu); /* RLC mem leak fix */
466 if (liCount > 0 || !( fi & 1))
468 rlcUtlSendUlDataToDu(gCb,rbCb,sdu);
477 If the SDU pointer has the last Data field of the PDU
478 -# If FI is 1,place the SDU in rbCb->m.um.umDl.partialSdu
479 -# else send the SDU to upper layer.
481 else if (count == liCount)
489 rlcUtlSendUlDataToDu(gCb, rbCb, sdu);
493 If the LI is something other than the first one,
494 just send the SDU to the upper layer */
497 rlcUtlSendUlDataToDu(gCb, rbCb, sdu);
500 rbCb->m.umUl.sn = sn;
506 * @brief Handler to process the re-establishment request received
507 * from the upper layer.
510 * This function does the following functions :
511 * - If direction of the RB is downlink :
512 * Remove all the SDUs in the SDU queue.
513 * - If direction of the RB is uplink :
514 * Call rlcUmmReAssembleSdus() for each PDU with SN < VR(UH)
516 * @param[in] gCb RLC Instance control block
517 * @param[in] rlcID Identity of the RLC entity for which
518 * re-establishment is to be done
519 * @param[in] rbCb RB control block for which re-establishment
525 Void rlcUmmUlReEstablish
532 Void rlcUmmUlReEstablish(gCb, rlcId, rbCb)
540 RlcUmRecBuf **recBuf; /* UM Reception Buffer */
541 RlcKwuSapCb *rlcKwSap; /* KWU SAP Information */
543 TRC2(rlcUmmUlReEstablish)
546 curSn = rbCb->m.umUl.vrUr;
547 vrUh = RLC_UM_GET_VALUE(rbCb->m.umUl.vrUh,rbCb->m.umUl);
548 recBuf = rbCb->m.umUl.recBuf;
550 if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
552 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
555 while (RLC_UM_GET_VALUE(curSn,rbCb->m.umUl) < vrUh)
557 if ( recBuf[curSn] != NULLP )
559 rlcUmmReAssembleSdus(gCb,rbCb,recBuf[curSn]);
560 RLC_FREE_WC(gCb,recBuf[curSn],sizeof(RlcUmRecBuf));
561 recBuf[curSn] = NULLP;
563 curSn = (curSn + 1) & rbCb->m.umUl.modBitMask;
565 rbCb->m.umUl.vrUr = 0;
566 rbCb->m.umUl.vrUh = 0;
567 rbCb->m.umUl.vrUx = 0;
569 rlcKwSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
571 /* In the UM Mode always send reestablish-indication to Upper Latyer*/
572 RlcUiKwuReEstCmpInd(&rlcKwSap->pst, rlcKwSap->suId, *rlcId);
578 * @brief Handler to extract the header from a PDU
581 * This function is used to extract the header of a PDU and store it
582 * along with the PDU buffer.The sequence number,framing info
583 * and LIs are extracted by this function.
585 * @param[in] gCb RLC Instance control block
586 * @param[in] rbCb Rb Control block for which the pdu is received
587 * @param[in] pdu PDU buffer
588 * @param[out] umHdr UM header to be filled after extraction
594 uint8_t rlcUmmExtractHdr(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *pdu, RlcUmHdr *umHdr)
596 uint8_t e; /* Extension Bit */
597 Data dst[2]; /* Destination Buffer */
598 int32_t totalSz; /* Sum of LIs */
599 MsgLen pduSz; /* PDU size */
600 #if (ERRCLASS & ERRCLS_DEBUG)
601 uint8_t ret; /* Return Value */
604 ODU_GET_MSG_LEN(pdu,&pduSz);
606 if ( rbCb->m.umUl.snLen == 1)
608 #if (ERRCLASS & ERRCLS_DEBUG)
609 ret = ODU_REM_PRE_MSG(dst,pdu);
612 DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed for 5 bit SN \
613 UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
617 ODU_REM_PRE_MSG(dst,pdu);
620 umHdr->sn = (dst[0]) & 0x1F;
621 umHdr->fi = (dst[0]) >> 6;
622 e = (dst[0]>>5) & 0x01;
626 /* snLen - sequnce length will be 10 bits requiring 2 bytes */
627 #if (ERRCLASS & ERRCLS_DEBUG)
628 ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
631 DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed for 10 bits SN \
632 UEID:%d CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
636 ODU_REM_PRE_MSG_MULT(dst,2,pdu);
640 /* kw005.201 R9 Upgrade 3gpp spec 36.322 ver9.3.0 CR0082 *
641 * Removed the "if" condition for checking the reserved field *
642 * Added mask 0x03 for extracting the FI field. */
644 umHdr->fi = ( (dst[0] ) >> 3) & 0x03;
645 e = ( (dst[0] ) >> 2) & 0x01;
646 umHdr->sn = ( dst[0] & 0x03) << 8;
653 while(e && umHdr->numLi < RLC_MAX_UL_LI )
655 #if (ERRCLASS & ERRCLS_DEBUG)
656 ret = ODU_REM_PRE_MSG_MULT(dst,2,pdu);
659 DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG_MULT Failed UEID:%d CELLID:%d",\
660 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
664 ODU_REM_PRE_MSG_MULT(dst,2,pdu);
666 umHdr->li[umHdr->numLi] = ((dst[0]) & 0x7F) << 4;
667 umHdr->li[umHdr->numLi] |= dst[1] >> 4;
668 if ( 0 == umHdr->li[umHdr->numLi] )
670 DU_LOG("\nRLC : rlcUmmExtractHdr : Received LI as 0 UEID:%d CELLID:%d",
671 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
674 totalSz += umHdr->li[umHdr->numLi];
675 if ( pduSz <= totalSz )
677 DU_LOG("\nRLC : rlcUmmExtractHdr : SN [%d]: UEID:%d CELLID:%d",\
678 umHdr->sn, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
679 DU_LOG("\nRLC : rlcUmmExtractHdr : Corrupted PDU as TotSz[%d] PduSz[%d] \
680 UEID:%d CELLID:%d ", totalSz, pduSz, rbCb->rlcId.ueId, rbCb->rlcId.cellId);
681 return RFAILED; /* the situation where in the PDU size
682 is something that does not match with
688 e = ((dst[0]) & 0x80) >> 7;
690 if ( e && umHdr->numLi < RLC_MAX_UL_LI)
692 U8 tmp = ((dst[1]) & 0x08) >> 3;
693 umHdr->li[umHdr->numLi] = ( dst[1] & 0x07) << 8;
696 #if (ERRCLASS & ERRCLS_DEBUG)
697 ret = ODU_REM_PRE_MSG(dst,pdu);
700 DU_LOG("\nRLC : rlcUmmExtractHdr : ODU_REM_PRE_MSG Failed UEID:%d CELLID:%d",
701 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
705 ODU_REM_PRE_MSG(dst,pdu);
707 umHdr->li[umHdr->numLi] |= ( dst[0] ); /* The first byte lies in
708 the first 8 bits.We want
709 them in the last 8 bits */
710 if ( 0 == umHdr->li[umHdr->numLi] )
712 DU_LOG("\nRLC : rlcUmmExtractHdr :Received LI as 0 UEID:%d CELLID:%d",
713 rbCb->rlcId.ueId, rbCb->rlcId.cellId);
716 totalSz += umHdr->li[umHdr->numLi];
722 return RFAILED; /* the situation where in the PDU size is
723 something that does not match with the
729 } /* while(e && umHdr->numLi < RLC_MAX_LI ) */
732 /* PDU was constructed with LIs that exceeded RLC_MAX_LI */
739 * @brief Handles expiry of re-ordering timer
741 * @param[in] gCb RLC Instance control block
742 * @param[in] rbCb Rb Control block for which re-order timer expired
747 Void rlcUmmReOrdTmrExp
753 Void rlcUmmReOrdTmrExp(gCb, rbCb)
758 RlcSn prevVrUr; /* prevVrUr */
760 TRC3(rlcUmmReOrdTmrExp)
763 prevVrUr = RLC_UMUL.vrUr;
765 /* set VR(UR) to SN >= VR(UX) that has not been received */
766 rlcUmmFindNextVRUR(&RLC_UMUL, RLC_UMUL.vrUx);
768 while (RLC_UM_GET_VALUE(prevVrUr,RLC_UMUL) <
769 RLC_UM_GET_VALUE(RLC_UMUL.vrUr,RLC_UMUL))
771 if (RLC_UMUL.recBuf[prevVrUr])
773 rlcUmmReAssembleSdus(gCb, rbCb, RLC_UMUL.recBuf[prevVrUr]);
774 if(RLC_UMUL.recBuf[prevVrUr]->pdu != NULLP) /* RLC mem leak fix */
776 RLC_FREE_BUF(RLC_UMUL.recBuf[prevVrUr]->pdu);
778 RLC_FREE_WC(gCb, RLC_UMUL.recBuf[prevVrUr], sizeof(RlcUmRecBuf));
779 RLC_UMUL.recBuf[prevVrUr] = NULLP;
782 prevVrUr = (prevVrUr + 1) & rbCb->m.umUl.modBitMask;
785 if (RLC_UM_GET_VALUE(RLC_UMUL.vrUh, RLC_UMUL) >
786 RLC_UM_GET_VALUE(RLC_UMUL.vrUr, RLC_UMUL))
788 rlcStartTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
789 RLC_UMUL.vrUx = RLC_UMUL.vrUh;
795 * Function to release/free the UnAcknowledged Mode Module RbCb buffers
798 * This primitive Frees the UM RbCb transmission Buffer, retransmission
799 * Buffer and reciption Buffers
801 * @param [in] gCb - RLC instance Control Block
802 * @param [in] rbCb - RB Control Block
808 Void rlcUmmFreeUlRbCb
814 Void rlcUmmFreeUlRbCb(gCb,rbCb)
819 RlcSn curSn = 0; /* sequence number of PDU */
820 RlcSn windSz; /* PDU window size */
821 RlcUmRecBuf **umRecBuf; /* UM module receive buffer */
823 TRC2(rlcUmmFreeUlRbCb)
826 windSz = rbCb->m.umUl.umWinSz << 1;
828 umRecBuf = rbCb->m.umUl.recBuf;
830 if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR))
832 rlcStopTmr(gCb,(PTR)rbCb,RLC_EVT_UMUL_REORD_TMR);
834 while (curSn < windSz)
836 if (umRecBuf[curSn] != NULLP)
838 RLC_FREE_BUF_WC(umRecBuf[curSn]->pdu);
839 umRecBuf[curSn]->pdu = NULLP;
841 RLC_FREE_WC(gCb, umRecBuf[curSn], sizeof(RlcUmRecBuf));
842 umRecBuf[curSn] = NULLP;
846 RLC_FREE_WC(gCb,rbCb->m.umUl.recBuf, (windSz ) * sizeof(RlcUmRecBuf*));
847 rbCb->m.umUl.recBuf = NULLP;
852 /********************************************************************30**
854 **********************************************************************/