59c337c137408747255f95739572fcde37dc4146
[o-du/l2.git] / src / 5gnrrlc / kw_amm_ul.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**
20
21         Name:    RLC - AM module file
22
23         Type:    C source file
24
25         Desc:    Source code for Acknowledged Mode Module functions such as,
26
27                  Transmission of data/control PDUs
28                  Retransmission (Feedback in terms of status)
29                  Polling
30                  Assemble SDUs
31                  Reception - reordering
32                  Duplicate detection for byte segments
33                  Reassemble SDUs
34
35         File:    kw_amm_ul.c
36
37 *********************************************************************21*/
38 static const char* RLOG_MODULE_NAME="AMM";
39 static int RLOG_MODULE_ID=2048;
40 static int RLOG_FILE_ID=190;
41
42 /* header include files (.h) */
43 #include "common_def.h"
44 #include "lkw.h"           /* LKW defines */
45 #include "ckw.h"           /* CKW defines */
46 #include "kwu.h"           /* KWU defines */
47 #include "rgu.h"           /* RGU defines */
48 #include "kw_udx.h"
49 #include "kw_err.h"        /* Err defines */
50 #include "kw_env.h"        /* RLC environment options */
51
52 #include "kw.h"            /* RLC defines */
53 #include "kw_ul.h"
54
55 /* extern (.x) include files */
56 #include "lkw.x"           /* LKW */
57 #include "ckw.x"           /* CKW */
58 #include "kwu.x"           /* KWU */
59 #include "rgu.x"           /* RGU */
60
61 #include "kw.x"
62 #include "kw_ul.x"
63 #include "kw_udx.x"
64
65 /* Variable for logging, declared in cl */
66 #ifndef RGL_SPECIFIC_CHANGES
67 #ifndef TENB_ACC
68 #ifndef LTE_PAL_ENB
69 extern U32 ulrate_rgu;
70 #endif
71 #endif
72 #endif
73 #ifndef RGL_SPECIFIC_CHANGES
74 #ifndef TENB_ACC
75 #ifndef TENB_T2K3K_SPECIFIC_CHANGES
76 #ifndef LTE_PAL_ENB
77 extern U32 isMemThreshReached(Region region);
78 #endif
79 #else
80 #ifndef LTE_PAL_ENB
81 extern U32  isMemThreshReached(Region region);
82 #endif
83 #endif
84 #endif
85 #endif
86 /** @file gp_amm_ul.c
87 @brief RLC Acknowledged Mode Uplink Module
88 **/
89 #define RLC_MODULE (RLC_DBGMASK_AM | RLC_DBGMASK_UL) /* for debugging purpose */
90
91 /* private function declarations */
92
93 PRIVATE Void rlcAmmUlAssembleCntrlInfo ARGS ((RlcCb *gCb, RlcUlRbCb *rbCb));
94
95 PRIVATE S16 rlcAmmExtractHdr ARGS ((RlcCb *gCb,
96                                 RlcUlRbCb   *rbCb,
97                                 Buffer *pdu,
98                                 RlcAmHdr *amHdr,
99                                 U8 *fByte));
100
101 PRIVATE Bool rlcAmmUlPlacePduInRecBuf ARGS ((RlcCb *gCb,
102                                             Buffer *pdu,
103                                             RlcUlRbCb *rbCb,
104                                             RlcAmHdr *amHdr));
105
106 PRIVATE Void rlcAmmTriggerStatus ARGS ((RlcCb *gCb,
107                                     RlcUlRbCb *rbCb,
108                                     RlcSn sn,
109                                     Bool discFlg));
110
111 PRIVATE S16  rlcAmmUlReassembleSdus ARGS ((RlcCb *gCb,
112                                      RlcUlRbCb *rbCb,
113                                      RlcAmRecBuf *recBuf));
114
115 PRIVATE Void rlcAmmProcPduOrSeg ARGS ((RlcCb *gCb,
116                                       RlcUlRbCb *rbCb,
117                                       RlcAmHdr *amHdr,
118                                       Buffer *pdu));
119
120 PRIVATE Void rlcAmmUpdExpByteSeg ARGS ((RlcCb *gCb,RlcAmUl *amUl, RlcSeg* newSeg));
121
122 PRIVATE Void rlcAmmExtractElmnt ARGS ((RlcCb *gCb, Buffer *pdu, RlcExtHdr *hdrInfo));
123
124 PRIVATE Void rlcAmmUlHndlStatusPdu ARGS ((RlcCb *gCb,
125                                          RlcUlRbCb *rbCb,
126                                          Buffer *cntrlPdu,
127                                          U8 *fByte));
128
129 /******************************************************************************
130
131   AM Module contains the following funcitons:
132
133   -  rlcAmmProcessSdus
134      -  rlcAmmUlAssembleCntrlInfo
135      -  rlcResegRetxPdus
136      -  rlcAssembleSdus
137      -  kwChkandSetPoll
138   -  rlcAmmProcessPdus
139      -  rlcAmmUlHndlStatusPdu
140      -  rlcAmmTriggerStatus
141      -  rlcAmmUlReassembleSdus
142
143 *******************************************************************************/
144 /** @addtogroup ammode */
145 /*@{*/
146
147 /**
148  * @brief   Private function to fill NACK information in status Pdu as per 5GNR
149  *
150  * @param[in]   rbCb       Ul RbCb
151  * @param[in]   sn         Sequence number of the PDU for which the NACK
152  * @param[in]   isSegment  TRUE means NACK for segment; FALSE for PDU
153  * @param[in]   soStart    SOStart
154  * @param[in]   soEnd      SOEnd
155  * @param[out]  statusPdu  status Pdu holder to be filled
156  * @param[in]   prevNackSn It holds previous nack Sn
157  *
158  * @return  S16
159  *    The number of bytes required to encode this NACK information
160  *
161  */
162 #ifdef ANSI
163 PRIVATE S16 rlcAmmUlSetNackInfo
164 (
165 RlcUlRbCb      *rbCb,
166 RlcSn          sn,
167 Bool          isSegment,
168 U16           soStart,
169 U16           soEnd,
170 RlcUdxDlStaPdu *statusPdu,
171 RlcSn          *prevNackSn
172 )
173 #else
174 PRIVATE S16 rlcAmmUlSetNackInfo(rbCb, sn, isSegment, soStart, statusPdu, prevNackSn)
175 RlcUlRbCb      *rbCb;
176 RlcSn          sn;
177 Bool          isSegment;
178 U16           soStart;
179 U16           soEnd;
180 RlcUdxDlStaPdu *statusPdu,
181 RlcSn          *prevNackSn;
182 #endif
183 {
184    RlcNackInfo   *nackInfo = (statusPdu->nackInfo + statusPdu->nackCount);
185    S16           sizeToBeEncd = 0; /* Status PDu size to be encoded */
186
187    TRC2(rlcAmmUlSetNackInfo)
188
189       /* In following cases we should increment the nackCnt & fill new NACK_SN info:
190        *    1) First NACK_SN of the statusdPdu
191        *    2) NACK_SN is not continuous with previous
192        *    3) NACK_SN is same as previuos but segments are not continuous
193        *    4) NACK_SN is continuous with previous but previous NACK_SN segments
194        *       are not missing in sequence till end
195        */
196       if((*prevNackSn == 0xffffffff) || ((((*prevNackSn) + 1) & AMUL.snModMask) != sn) ||
197             (((*prevNackSn) == sn) && (((nackInfo->soEnd + 1) != soStart))) ||
198             ((nackInfo->isSegment) && (((*prevNackSn) + 1) == sn) && (nackInfo->soEnd != RLC_ALL_BYTES_MISSING)))
199       {
200          if(nackInfo->nackRange)
201          {
202             if((nackInfo->soEnd) && (!nackInfo->soStart))
203             {
204                /*First nack_sn of this nackRange not segmented but last is segmented */
205                sizeToBeEncd = 5; /*32 for soStart and soEnd and 8 for nackRange */ 
206             }
207             else
208             {
209                /*First nack_sn of this nackRange was segmented */
210                sizeToBeEncd = 1; /*8 for nackRange */ 
211             }
212          }
213
214          if(*prevNackSn != 0xffffffff)
215          {
216             /* Increment nackCount as this sn is continous */
217             statusPdu->nackCount++;
218             nackInfo = statusPdu->nackInfo + statusPdu->nackCount;
219          }
220
221          nackInfo->sn = sn;
222          nackInfo->isSegment = isSegment;
223          nackInfo->soStart = soStart;
224          nackInfo->soEnd   = soEnd;
225          nackInfo->nackRange = 0;
226
227          if(isSegment)
228          {
229             sizeToBeEncd += ((AMUL.snLen == RLC_AM_CFG_12BIT_SN_LEN)?6:7); /* NACK,E1,E2,Sostart,SoEnd */
230          }
231          else
232          {
233             sizeToBeEncd += ((AMUL.snLen == RLC_AM_CFG_12BIT_SN_LEN)?2:3); /* NACK,E1,E2 */
234          }
235       }
236       else
237       {
238          if(!(nackInfo->nackRange))
239          {
240             nackInfo->nackRange++;
241          }
242          /* This case means there are continuous SNs/Segments. If it is the next
243           * Sn then increment nackRnage. if same SN but different segment then
244           * dont increment nackRange */
245          if((((*prevNackSn) + 1) & AMUL.snModMask) == sn)
246          {
247             nackInfo->nackRange++;
248          }
249
250          /* If NackRange is reached to max value then increment statusPdu->nackCount*/
251          if(nackInfo->nackRange == 255)
252          {
253             statusPdu->nackCount++;
254             if(nackInfo->isSegment)
255             {
256                sizeToBeEncd = 1; /* return only nackRangeSize*/
257             }
258             else if (isSegment)
259             {
260                /* First SN was not segmented of this nackRange but last SN is segmented */
261                sizeToBeEncd = 5; /* return size of soSatrt + soEnd + nackRnage */
262             }
263          }
264
265          if(isSegment)
266          {
267             nackInfo->isSegment = isSegment;
268             nackInfo->soEnd = soEnd;
269          }
270          else if(nackInfo->isSegment)
271          {
272             nackInfo->soEnd = RLC_ALL_BYTES_MISSING;
273          }
274          else
275          {
276             nackInfo->soStart = 0;
277             nackInfo->soEnd =   0;
278          }
279
280       }
281    *prevNackSn = sn;
282
283    return (sizeToBeEncd);
284 }
285
286 /**
287  * @brief   Private handler to gather information required to create the STATUS
288  *          PDU
289  *
290  * @details
291  *    Scans the reception buffer and copies information to the UdxDlStaPdu
292  *    structure about SN's  and segments not yet received. This data is
293  *    sent to the DL instance so that it can create an appropriate (depending
294  *    on the grants from MAC) STATUS PDU and send it to MAC.
295  *
296  * @param[in]  gCb      RLC instance control block
297  * @param[in]  rbCb     Uplink RB control block
298  *
299  * @return  Void
300  *
301  */
302 #ifdef ANSI
303 PRIVATE Void rlcAmmUlAssembleCntrlInfo
304 (
305 RlcCb       *gCb,
306 RlcUlRbCb   *rbCb
307 )
308 #else
309 PRIVATE Void rlcAmmUlAssembleCntrlInfo(gCb, rbCb)
310 RlcCb       *gCb;
311 RlcUlRbCb   *rbCb;
312 #endif
313 {
314    RlcUdxDlStaPdu   *pStatusPdu;
315    RlcNackInfo      *nackInfo;
316    RlcSn            sn;                /* sequence number */
317    RlcSn            mSn;               /* Mod val of sequence number */
318    RlcSn            rxHighestStatus;              /* Mod val of rxHighestStatus */
319    RlcSeg           *seg;              /* pdu segment */
320    U16             nackCnt = 0;       /* Index for staPdu */
321    U16             seqSo;             /* segmment offset */
322    RlcUdxUlSapCb    *sapCb;
323    U16             staPduEncSize = 3; /* size that would be of the encoded
324                                           STATUS PDU, it is in bits; 15 for
325                                           first fixed part of STATUS PDU */
326    RlcAmRecBuf      *recBuf = NULLP;
327    RlcSn            prevNackSn = 0xffffffff;
328
329    TRC2(rlcAmmUlAssembleCntrlInfo)
330
331
332    sapCb = RLC_GET_UDX_SAP(gCb);
333
334    RLC_ALLOC_SHRABL_BUF(sapCb->pst.region,
335                        sapCb->pst.pool,
336                        pStatusPdu, 
337                        sizeof(RlcUdxDlStaPdu)); 
338
339 #if (ERRCLASS & ERRCLS_ADD_RES)
340    /* Memory allocation failure can not be expected  */
341    if(!pStatusPdu)
342    {
343      RETVOID;
344    }
345 #endif
346
347    sn = AMUL.rxNext;
348    MODAMR(sn, mSn, AMUL.rxNext, AMUL.snModMask);
349    MODAMR(AMUL.rxHighestStatus, rxHighestStatus, AMUL.rxNext, AMUL.snModMask);
350    
351    recBuf =  rlcUtlGetRecBuf(AMUL.recBufLst, sn);
352
353    while (mSn < rxHighestStatus )
354    {
355       /* For missing PDUs */
356       if ((NULLP  == recBuf) && nackCnt < RLC_MAX_NACK_CNT )
357       {
358          RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, 
359                   "Missing PDU's SN = %d UEID:%d CELLID:%d", 
360                   sn,
361                   rbCb->rlcId.ueId,
362                   rbCb->rlcId.cellId);
363          staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
364                                              sn,
365                                              FALSE, /* isSegment */
366                                              0,     /* SOStart */
367                                              0,     /* SOEnd */
368                                              pStatusPdu,
369                                              &prevNackSn);
370       }
371       else if (recBuf && (recBuf->pdu == NULLP) &&
372                (recBuf->segLst.count > 0))
373       {
374          /* Scan through the byte segments of PDU and add this sn
375             with soStart and soEnd info to staPdu */
376
377          seqSo  = 0;
378          RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
379          while (seg != NULLP && nackCnt < RLC_MAX_NACK_CNT)
380          {
381             /* For missing byte segments */
382             if (seg->amHdr.so != seqSo)
383             {
384                staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
385                                                    sn,
386                                                    TRUE,
387                                                    seqSo,
388                                                    seg->amHdr.so - 1,
389                                                    pStatusPdu,
390                                                    &prevNackSn);
391
392                RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
393                              "Missing byte segment's" 
394                              " SN:%d UEID:%d CELLID:%d",
395                              sn,
396                              rbCb->rlcId.ueId,
397                              rbCb->rlcId.cellId);
398                RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
399                              "soStart and soEnd = %d, %d UEID:%d CELLID:%d",
400                              seqSo,
401                              seg->amHdr.so - 1,
402                              rbCb->rlcId.ueId,
403                              rbCb->rlcId.cellId);
404             }
405
406             seqSo = seg->soEnd + 1;
407             RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
408          }
409
410          /* Check if the last segment is missing */
411          RLC_LLIST_LAST_SEG(recBuf->segLst, seg);
412          if ((seg != NULLP) &&
413              (seg->amHdr.si != RLC_SI_LAST_SEG && nackCnt < RLC_MAX_NACK_CNT))
414          {
415             staPduEncSize += rlcAmmUlSetNackInfo(rbCb,
416                                                 sn,
417                                                 TRUE,
418                                                 seqSo,
419                                                 RLC_ALL_BYTES_MISSING,
420                                                 pStatusPdu,
421                                                 &prevNackSn);
422
423             RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
424                           "rlcAmmUlAssembleCntrlInfo: Missing (last) byte " 
425                           "segment's SN:%d UEID:%d CELLID:%d",
426                           sn,
427                           rbCb->rlcId.ueId,
428                           rbCb->rlcId.cellId);
429             RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
430                           "soStart and soEnd = %d, %d UEID:%d CELLID:%d",
431                           seqSo,
432                           RLC_ALL_BYTES_MISSING,
433                           rbCb->rlcId.ueId,
434                           rbCb->rlcId.cellId);
435          }
436       }
437       
438
439       sn = (sn + 1) & (AMUL.snModMask); /* MOD 1024 */
440       MODAMR(sn, mSn, AMUL.rxNext, AMUL.snModMask);
441       
442       /* Get the received Buffer the updated/next SN */
443       recBuf =  rlcUtlGetRecBuf(AMUL.recBufLst, sn);
444
445       /* Find the next missing sequence number if nackCnt reaches maximum and
446          still Reordering window has some missing AMDPDUs / AMDPDU segments. The
447          next missing sequence number will be considered as the ack sequnece
448          number in the status pdu.*/
449       if((nackCnt == RLC_MAX_NACK_CNT) &&
450           ((recBuf == NULLP) ||
451             ((recBuf->pdu == NULLP) &&
452              (recBuf->segLst.count > 0))))
453       {
454          break;
455       }
456    }
457  
458    /*Unfortunately i have write below peice of code here because kwAmmsetNackInfo()
459     * don't know that this is the last nackSn with nackRange*/
460    nackInfo = &(pStatusPdu->nackInfo[pStatusPdu->nackCount]);
461    if(nackInfo->nackRange)
462    {
463       if((nackInfo->soEnd) && (!nackInfo->soStart))
464       {
465          /*First nack_sn of this nackRange not segmented but last is segmented */
466          staPduEncSize += 5; /*32 for soStart and soEnd and 8 for nackRange */ 
467       }
468       else
469       {
470          /*First nack_sn of this nackRange was segmented */
471          staPduEncSize += 1; /*8 for nackRange */ 
472       }
473    }
474    /* nackCount is used as an index to nackInfo array but in status Pdu it
475     * should be equal to number nackInfo that are filled. hence incrementing by 1*/
476    if(prevNackSn != 0xffffffff)
477    {
478       pStatusPdu->nackCount++;
479    }
480    /* Update ACK SN with the last sn for which feedback is not assembled */
481    if ( mSn == rxHighestStatus)
482    {
483       pStatusPdu->ackSn = AMUL.rxHighestStatus;
484    }
485    else
486    {
487       pStatusPdu->ackSn = sn;
488    }
489
490    RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId,
491             "rlcAmmUlAssembleCntrlInfo: ACK PDU's SN = %d"
492             "UEID:%d CELLID:%d",
493             pStatusPdu->ackSn,
494             rbCb->rlcId.ueId,
495             rbCb->rlcId.cellId);
496
497    pStatusPdu->controlBo = staPduEncSize; /*Its already in bytes */
498
499    AMUL.staTrg = FALSE;
500    AMUL.gatherStaPduInfo = FALSE;
501
502
503    if (rlcUlUdxStaPduReq(&sapCb->pst,
504                         sapCb->spId,
505                         &rbCb->rlcId,
506                         pStatusPdu) != ROK)
507    {
508       RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
509                "Failed to Send Sta Pdu UEID:%d CELLID:%d",
510                rbCb->rlcId.ueId,
511                rbCb->rlcId.cellId);
512       RLC_FREE_SHRABL_BUF_WC(sapCb->pst.region,
513                             sapCb->pst.pool,
514                             pStatusPdu, 
515                             sizeof(RlcUdxDlStaPdu));
516    }
517
518    RETVOID;
519 }
520
521 #ifdef XEON_SPECIFIC_CHANGES
522 extern U32  gRlcDatIndUL;
523 #endif
524
525 #ifdef T2K_TRIGGER_RLC_REEST
526 U32 drpRlcDrbPack;
527 #endif
528 /**
529  * @brief Handler to process the PDUs received from MAC and send it to PDCP
530  *
531  * @details
532  *    This function is invoked by UTL with the PDU(s) received from MAC.
533  *    It reorders the received data PDUs and trigger status report as
534  *    needed. Reassembles the SDUs in sequence and send it to PDCP.
535  *    It also processes the control PDU
536  *
537  * @param[in]  gCb      RLC instance control block
538  * @param[in]  rbCb     RB control block
539  * @param[out] pduInfo  PDU Info received from MAC
540  *
541  *  @return Void
542  *
543  */
544 #ifdef LTE_L2_MEAS
545 #ifdef ANSI
546 Void rlcAmmProcessPdus
547 (
548 RlcCb                    *gCb,
549 RlcUlRbCb                *rbCb,
550 KwPduInfo               *pduInfo,
551 U32                     ttiCnt
552 )
553 #else
554 Void rlcAmmProcessPdus(gCb, rbCb, pduInfo, ulTimeInfo)
555 RlcCb                    *gCb;
556 RlcUlRbCb                *rbCb;
557 KwPduInfo               *pduInfo;
558 U32                     ttiCnt;
559 #endif
560 #else
561 #ifdef ANSI
562 Void rlcAmmProcessPdus
563 (
564 RlcCb        *gCb,
565 RlcUlRbCb    *rbCb,
566 KwPduInfo   *pduInfo
567 )
568 #else
569 Void rlcAmmProcessPdus(gCb, rbCb, pduInfo)
570 RlcCb        *gCb;
571 RlcUlRbCb    *rbCb;
572 KwPduInfo   *pduInfo;
573 #endif
574 #endif
575 {
576    Buffer    *pdu;
577    RlcAmUl    *amUl;
578    RlcAmHdr   amHdr;
579    U8        numPdu = 0;
580    U8        numPduToProcess;
581    RlcSn      sn;
582    RlcSn      tSn;
583    RlcSn      mSn;
584    U8        fByte;
585    Bool      discFlg;
586 #ifdef LTE_L2_MEAS_RLC
587    MsgLen              rlcSduSz;  /*Holds length of Rlc Sdu*/
588 #endif /* LTE_L2_MEAS */
589
590    TRC2(rlcAmmProcessPdus)
591
592
593    amUl = &AMUL;
594
595    numPduToProcess = RLC_MIN(pduInfo->numPdu, RGU_MAX_PDU);
596    RLOG_ARG4(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId, 
597             "numPdu[%ld],numPduToProcess[%ld] UEID:%ld CELLID:%ld",
598             numPdu,
599             numPduToProcess,
600             rbCb->rlcId.ueId,
601             rbCb->rlcId.cellId);
602
603    //printf ("++++++++++++  5GNRLOG numPduToProcess %d \n", numPduToProcess);
604    while (numPdu < numPduToProcess)
605    {
606    //printf ("++++++++++++  5GNRLOG processing pdu  %d \n", numPdu);
607       discFlg = FALSE;
608       pdu = pduInfo->mBuf[numPdu++];
609
610       if (! pdu)
611       {
612
613          RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
614                   "Null Pdu UEID:%d CELLID:%d",
615                   rbCb->rlcId.ueId,
616                   rbCb->rlcId.cellId);
617          gCb->genSts.errorPdusRecv++;
618          break;
619       }
620 #ifndef RGL_SPECIFIC_CHANGES
621 #ifndef TENB_ACC
622 #ifndef LTE_PAL_ENB
623       MsgLen len;
624       SFndLenMsg(pdu, &len);
625       ulrate_rgu += len;
626 #endif
627 #endif
628 #endif      
629       /* Extract AM PDU/SEG header Info */
630       RLC_MEM_ZERO(&amHdr, sizeof(RlcAmHdr));
631       /* Avoided the allocation of amHdr and sending
632          a single pointer */
633       if (rlcAmmExtractHdr(gCb, rbCb, pdu, &amHdr, &fByte) != ROK)
634       {
635          RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
636                   "Header Extraction Failed UEID:%d CELLID:%d",
637                   rbCb->rlcId.ueId,
638                   rbCb->rlcId.cellId);
639          RLC_FREE_BUF(pdu);
640          gCb->genSts.errorPdusRecv++;
641          continue;
642       }
643       /* Check if its a control PDU */
644       if (amHdr.dc == 0)
645       {
646          rlcAmmUlHndlStatusPdu(gCb, rbCb, pdu, &fByte);
647          RLC_FREE_BUF(pdu);
648          continue;
649       }
650       if((amHdr.si == RLC_SI_LAST_SEG) && (!amHdr.so))
651       {
652          RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId,
653                "rlcAmmProcessPdus: Dropping PDU because SO can't be zero for last segment sn:%u "
654                "UEID:%d CELLID:%d",
655                amHdr.sn,
656                rbCb->rlcId.ueId,
657                rbCb->rlcId.cellId);
658          RLC_FREE_BUF(pdu);
659          continue;
660       }
661 #ifndef RGL_SPECIFIC_CHANGES
662 #ifdef LTE_TDD
663 #ifndef TENB_ACC
664 #ifndef TENB_T2K3K_SPECIFIC_CHANGES
665 #ifndef LTE_PAL_ENB
666     /* Changed the condition to TRUE from ROK  */
667       if(isMemThreshReached(rlcCb[0]->init.region) == TRUE)
668       {
669          extern U32 rlculdrop;
670          rlculdrop++;
671          RLC_FREE_BUF(pdu);
672          continue;
673       }
674 #endif
675 #else
676 #ifndef LTE_PAL_ENB
677       /*ccpu00142274 - UL memory based flow control*/
678       if(isMemThreshReached(rlcCb[0]->init.region) != ROK)
679       {
680          extern U32 rlculdrop;
681          rlculdrop++;
682          RLC_FREE_BUF(pdu);
683          continue;
684       }
685 #endif
686 #endif
687 #endif
688 #endif
689 #endif
690
691 #ifdef T2K_TRIGGER_RLC_REEST
692       if(drpRlcDrbPack > 1000)
693       {
694          if(rbCb->rlcId.rbType == CM_LTE_DRB)
695          {
696             RLC_FREE_BUF(pdu);
697             continue;
698          }
699       }
700       drpRlcDrbPack++;
701 #endif
702       /* Reordering data PDU */
703       sn = amHdr.sn;
704       if (rlcAmmUlPlacePduInRecBuf(gCb,pdu, rbCb, &amHdr) == TRUE)
705       {
706          RlcAmRecBuf      *recBuf;
707          Bool   tmrRunning;
708          RlcSn   tVrMr;
709          RlcSn   mrxNextHighestRcvd;
710
711 #ifdef LTE_L2_MEAS
712          rlcUtlCalUlIpThrPut(gCb, rbCb, pdu, ttiCnt);
713 #endif /* LTE_L2_MEAS */
714
715          /* Update rxNextHighestRcvd */
716          MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
717          MODAMR(amUl->rxNextHighestRcvd, mrxNextHighestRcvd, amUl->rxNext, amUl->snModMask);
718          if (mSn >= mrxNextHighestRcvd)
719          {
720             amUl->rxNextHighestRcvd = ((sn + 1) & (amUl->snModMask)); 
721
722             RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId,
723                   "rlcAmmProcessPdus: Updated rxNextHighestRcvd = %d UEID:%d CELLID:%d",
724                   amUl->rxNextHighestRcvd,
725                   rbCb->rlcId.ueId,
726                   rbCb->rlcId.cellId);
727          }
728          
729          recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
730          if ((NULLP != recBuf) && ( recBuf->allRcvd))
731          {
732             /* deliver the reassembled RLC SDU to upper layer, 
733                But not removed from the table */
734             rlcAmmUlReassembleSdus(gCb, rbCb, recBuf);
735             recBuf->isDelvUpperLayer = TRUE;
736
737             MODAMR(amUl->vrMr, tVrMr, amUl->rxNext, amUl->snModMask);
738             
739             /* Update rxHighestStatus */
740             if (sn == amUl->rxHighestStatus)
741             {
742                tSn = (sn + 1) & (amUl->snModMask) ; /* MOD (2 Pwr SN LEN- 1) */
743
744                recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
745                /* Scan through till the upper edge of the window */
746                MODAMR(tSn, mSn, amUl->rxNext, amUl->snModMask);
747                while (mSn <= tVrMr)
748                {
749                   if ((NULLP == recBuf) || (!recBuf->allRcvd))
750                   {
751                      RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId,
752                            "rlcAmmProcessPdus: Updated rxHighestStatus:%d "
753                            "UEID:%d CELLID:%d",
754                            tSn,
755                            rbCb->rlcId.ueId,
756                            rbCb->rlcId.cellId);
757
758                      amUl->rxHighestStatus = tSn;
759                      break;
760                   }
761                   tSn = (tSn + 1) & (amUl->snModMask); /* MOD (2 Pwr SN LEN- 1) */
762                   recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn); 
763                   mSn++;
764                }
765             }
766
767
768             /* Update rxNext */
769             if (sn == amUl->rxNext)
770             {
771                tSn = sn;
772                recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
773                MODAMR(tSn, mSn, amUl->rxNext, amUl->snModMask);
774                /* Scan through till the upper edge of the window */
775                while (mSn <= tVrMr)
776                {
777                   if ((NULLP != recBuf) && (recBuf->allRcvd) &&
778                       (TRUE == recBuf->isDelvUpperLayer))
779                   {
780                      /* RecBuf should remove from table 
781                         since PDU is already sent to upper layer */
782                       recBuf->isDelvUpperLayer = FALSE;
783                       rlcUtlDelRecBuf(amUl->recBufLst, recBuf, gCb);
784                   }
785                   else
786                   {
787                      amUl->rxNext = tSn;
788                      amUl->vrMr = (amUl->rxNext + (RLC_AM_GET_WIN_SZ(amUl->snLen))) & (amUl->snModMask);
789                      break;
790                   }
791                   tSn = (tSn + 1) & (amUl->snModMask); 
792                   recBuf = rlcUtlGetRecBuf(amUl->recBufLst, tSn);
793                   mSn++;
794                }
795             }
796          }
797
798          /* Check if reOrdTmr is running and update rxNextStatusTrig accordingly */
799          tmrRunning = rlcChkTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
800          if (tmrRunning)
801          {
802             Bool snInWin = RLC_AM_CHK_SN_WITHIN_RECV_WINDOW(amUl->rxNextStatusTrig, amUl);
803
804             if ( (amUl->rxNextStatusTrig == amUl->rxNext) || ( (!snInWin) &&
805                                              (amUl->rxNextStatusTrig != amUl->vrMr) ) )
806             {
807                rlcStopTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
808                tmrRunning = FALSE;
809             }
810          }
811
812          if (!tmrRunning)
813          {
814             if (amUl->rxNextHighestRcvd > amUl->rxNext)
815             {
816                rlcStartTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
817                amUl->rxNextStatusTrig = amUl->rxNextHighestRcvd;
818
819                RLOG_ARG3(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
820                         "rlcAmmProcessPdus: Updated rxNextStatusTrig = %d UEID:%d CELLID:%d",
821                         amUl->rxNextStatusTrig,
822                         rbCb->rlcId.ueId,
823                         rbCb->rlcId.cellId);
824             }
825          }
826       }
827       else
828       {
829          discFlg = TRUE;
830          gRlcStats.amRlcStats.numULPdusDiscarded++;
831       }
832
833       if (amHdr.p)
834       {
835          rlcAmmTriggerStatus(gCb,rbCb, sn, discFlg);
836       }
837    }
838
839 #ifdef LTE_L2_MEAS
840    rlcUtlCalUlIpThrPutIncTTI(gCb, rbCb,ttiCnt);
841 #endif /* LTE_L2_MEAS */
842    gCb->genSts.pdusRecv += pduInfo->numPdu;
843    if (amUl->gatherStaPduInfo)
844    {
845       rlcAmmUlAssembleCntrlInfo(gCb,rbCb);
846    }
847
848    RETVOID;
849 }
850
851
852 /**
853  * @brief Private handler to extract header Information of the PDU
854  *
855  * @details
856  *    This function extracts the header elements of the PDU and store them
857  *    in db for future reference.
858  *
859  *    fByte - is the first byte removed from the PDU as part of calling
860  *            functions
861  *
862  * @param[in]  gCb     RLC instance control block
863  * @param[in]  rbCb    Uplink RB control block
864  * @param[in]  pdu     Received PDU
865  * @param[out] amHdr   Pointer to the extracted AM header
866  * @param[out] fByte   First byte removed from the PDU
867  *
868  * @return S16
869  *     -# ROK
870  *     -# RFAILED
871  *
872  */
873 #ifdef ANSI
874 PRIVATE S16 rlcAmmExtractHdr
875 (
876 RlcCb       *gCb,
877 RlcUlRbCb   *rbCb,
878 Buffer     *pdu,
879 RlcAmHdr    *amHdr,
880 U8         *fByte
881 )
882 #else
883 PRIVATE S16 rlcAmmExtractHdr(gCb, rbCb, pdu, amHdr, fByte)
884 RlcCb       *gCb;
885 RlcUlRbCb   *rbCb;
886 Buffer     *pdu;
887 RlcAmHdr    *amHdr;
888 U8         *fByte;
889 #endif
890 {
891    U8         snByte;
892    RlcSn        sn = 0;
893    MsgLen     pduSz;
894    RlcExtHdr   hdrInfo;
895
896    TRC2(rlcAmmExtractHdr)
897
898
899    RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
900
901    /* Extract fixed part of the header */
902    SFndLenMsg(pdu,&pduSz);
903    SRemPreMsg(fByte, pdu);
904    amHdr->dc = (*fByte & RLC_DC_POS) >> RLC_DC_SHT;
905    if (RLC_CNTRL_PDU == amHdr->dc)
906    {
907    //printf ("++++++++++++ 5GNRLOG HDR extracted CTRL : \n");
908       return ROK;
909    }
910
911    amHdr->p  = (*fByte & RLC_POLL_POS) >> RLC_POLL_SHT;
912
913    amHdr->si = (*fByte & RLC_SI_POS)   >> RLC_SI_SHT;
914
915    /* 12 BIT SN */
916    if (rbCb->m.amUl.snLen == RLC_AM_CFG_12BIT_SN_LEN)
917    {
918       SRemPreMsg(&snByte, pdu);
919       sn = (RlcSn)(((*fByte & RLC_SN_POS_12BIT) << RLC_BYTE_LEN ) | snByte);
920       amHdr->sn = sn;
921    }
922    else if (rbCb->m.amUl.snLen == RLC_AM_CFG_18BIT_SN_LEN)
923    {
924       SRemPreMsg(&snByte, pdu);
925       sn = (RlcSn)(((*fByte & RLC_SN_POS_18BIT) << RLC_BYTE_LEN ) | snByte);
926
927       SRemPreMsg(&snByte, pdu);
928       sn = ((sn << RLC_BYTE_LEN) | snByte);
929
930       amHdr->sn = sn;
931    }
932    if ((amHdr->si != 0) && (amHdr->si != 0x01))
933    {
934       hdrInfo.len = RLC_SO_LEN_5GNR;
935       rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
936       amHdr->so = hdrInfo.val;
937       pduSz -= 2;
938    }
939
940    //printf ("++++++++++++ 5GNRLOG HDR extracted DATA : sn %d  \n", sn);
941    return ROK;
942 }
943
944 #ifdef OLD
945 /**
946  * @brief Private handler to extract header Information of the PDU
947  *
948  * @details
949  *    This function extracts the header elements of the PDU and store them
950  *    in db for future reference.
951  *
952  *    fByte - is the first byte removed from the PDU as part of calling
953  *            functions
954  *
955  * @param[in]  gCb     RLC instance control block
956  * @param[in]  rbCb    Uplink RB control block
957  * @param[in]  pdu     Received PDU
958  * @param[out] amHdr   Pointer to the extracted AM header
959  * @param[out] fByte   First byte removed from the PDU
960  *
961  * @return S16
962  *     -# ROK
963  *     -# RFAILED
964  *
965  */
966 #ifdef ANSI
967 PRIVATE S16 rlcAmmExtractHdrOld
968 (
969 RlcCb       *gCb,
970 Buffer     *pdu,
971 RlcAmHdr    *amHdr,
972 U8         *fByte
973 )
974 #else
975 PRIVATE S16 rlcAmmExtractHdrOld(gCb, pdu, amHdr, fByte)
976 RlcCb       *gCb;
977 Buffer     *pdu;
978 RlcAmHdr    *amHdr;
979 U8         *fByte;
980 #endif
981 {
982    U8         e;
983    U8         snByte;
984    U16        sn;
985    MsgLen     pduSz;
986    MsgLen     totalSz = 0;
987    RlcExtHdr   hdrInfo;
988
989    TRC2(rlcAmmExtractHdrOld)
990
991
992    RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
993
994    /* Extract fixed part of the header */
995    SFndLenMsg(pdu,&pduSz);
996    SRemPreMsg(fByte, pdu);
997    amHdr->dc = (*fByte & RLC_DC_POS) >> RLC_DC_SHT;
998    if (RLC_CNTRL_PDU == amHdr->dc)
999    {
1000       return ROK;
1001    }
1002    /* kw002.201 : Changed the extraction of hdr elements to avoid */
1003    /*             function calls                                  */
1004    amHdr->rf = (*fByte & RLC_RF_POS)   >> RLC_RF_SHT;
1005    amHdr->p  = (*fByte & RLC_POLL_POS) >> RLC_POLL_SHT;
1006    amHdr->fi = (*fByte & RLC_FI_POS)   >> RLC_FI_SHT;
1007    e = amHdr->e  = (*fByte & RLC_E_POS)>> RLC_E_SHT;
1008     
1009    SRemPreMsg(&snByte, pdu);
1010    sn = (U16)(((*fByte & RLC_SN_POS) << RLC_BYTE_LEN ) | snByte);
1011    amHdr->sn = sn;
1012    if (amHdr->rf == 1)
1013    {
1014       /* Extract extn part of the header */
1015       hdrInfo.len = RLC_LSF_LEN;
1016       rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
1017       amHdr->lsf = (U8)hdrInfo.val;
1018
1019       hdrInfo.len = RLC_SO_LEN;
1020       rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
1021       amHdr->so = hdrInfo.val;
1022       pduSz -= 2;
1023    }
1024
1025    amHdr->numLi = 0;
1026    /* Extract LIs */
1027    while (e && (amHdr->numLi < RLC_MAX_UL_LI))
1028    {
1029       hdrInfo.len = RLC_E_LEN;
1030       rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
1031       e = amHdr->e = (U8)hdrInfo.val;
1032
1033       /* Extract LI value*/
1034       hdrInfo.len = RLC_LI_LEN;
1035       rlcAmmExtractElmnt(gCb, pdu, &hdrInfo);
1036       /* li = hdrInfo.val;*/
1037
1038       /* check if LI is zero */
1039       if (! hdrInfo.val)
1040       {
1041          RLOG0(L_ERROR, "Received LI as 0");
1042          return RFAILED;
1043       }
1044
1045       /* store the extracted  LI value */
1046       amHdr->li[amHdr->numLi++] = hdrInfo.val;
1047       totalSz += hdrInfo.val;  /* incrment the size by LI value */
1048    }
1049
1050    /*ccpu00122597:PDU is dropped if liCnt exceeds RLC_MAX_LI*/
1051    if(e && (amHdr->numLi >= RLC_MAX_UL_LI))
1052    {
1053       RLOG2(L_ERROR,"LI Count [%u] exceeds Max LI Count[%u]", 
1054             amHdr->numLi, RLC_MAX_UL_LI);
1055       return RFAILED;
1056    }
1057
1058    /*                                first 2 bytes + Add one for  Odd LI*/
1059    pduSz -= ( amHdr->numLi + (amHdr->numLi >> 1) + 2 + (amHdr->numLi & 1) );
1060
1061    if ( totalSz >= pduSz )
1062    {   
1063       RLOG3(L_ERROR,"SN [%d]:Corrupted PDU as TotSz[%lu] PduSz[%lu] ",
1064                amHdr->sn, totalSz, pduSz);
1065       return RFAILED;
1066    }
1067
1068    return ROK;
1069 }
1070 #endif
1071
1072 /**
1073  * @brief Private handler to process the status PDU
1074  *
1075  * @details
1076  *    Private handler invokded by rlcAmmProcessPdus to process the
1077  *    control PDU (status report) received from its peer RLC entity.
1078  *
1079  *        - Decode the values from the received control pdu
1080  *        - Create a RlcUdxStaPdu structure, copy the values onto it and
1081  *          send it to the DL instance for further processing
1082  *
1083  * @param[in]  gCb       RLC instance control block
1084  * @param[in]  rbCb      Uplink RB control block
1085  * @param[in]  cntrlPdu  Control PDU received from MAC
1086  * @param[in]  fByte     First byte already removed from the STATUS PDU
1087  *
1088  *  @return  Void
1089  *
1090  */
1091 #ifdef ANSI
1092 PRIVATE Void rlcAmmUlHndlStatusPdu
1093 (
1094 RlcCb       *gCb,
1095 RlcUlRbCb   *rbCb,
1096 Buffer     *cntrlPdu,
1097 U8         *fByte
1098 )
1099 #else
1100 PRIVATE Void rlcAmmUlHndlStatusPdu(gCb, rbCb, cntrlPdu, fByte)
1101 RlcCb       *gCb;
1102 RlcUlRbCb   *rbCb;
1103 Buffer     *cntrlPdu;
1104 U8         *fByte;
1105 #endif
1106 {
1107    U8             e1;
1108    RlcExtHdr       hdrInfo;
1109    RlcUdxStaPdu    *pStaPdu;
1110    RlcUdxUlSapCb   *sapCb;
1111    U8             e3; /* NACK RANGE : 5GNR */
1112    U32            snLen;
1113    U32            snRange;
1114    U32            resrvdBitsAckSn=0;
1115    U32            resrvdBitsNackSn=0;
1116
1117    TRC2(rlcAmmUlHndlStatusPdu)
1118
1119
1120    RLC_MEM_ZERO(&hdrInfo, sizeof(RlcExtHdr));
1121
1122    /* Extract the Control PDU */
1123    hdrInfo.hdr  = (*fByte << 1);
1124    hdrInfo.pLen = 4;
1125
1126    /* D/C has been shifted in the calling function */
1127    if (hdrInfo.hdr & 0xE0)
1128    {
1129       RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId,
1130                "Reserved value for CPT received UEID:%d CELLID:%d",
1131                rbCb->rlcId.ueId,
1132                rbCb->rlcId.cellId);
1133
1134       RETVOID;
1135    }
1136
1137    sapCb = RLC_GET_UDX_SAP(gCb);
1138
1139    RLC_ALLOC_SHRABL_BUF(sapCb->pst.region, 
1140                        sapCb->pst.pool, 
1141                        pStaPdu, 
1142                        sizeof(RlcUdxStaPdu));
1143
1144 #if (ERRCLASS & ERRCLS_ADD_RES)
1145    /* Memory allocation failure can not be expected  */
1146    if(!pStaPdu)
1147    {
1148      RETVOID;
1149    }
1150 #endif   
1151
1152    if (rbCb->m.amUl.snLen == RLC_AM_CFG_12BIT_SN_LEN)
1153    {
1154       snLen = 12;
1155       resrvdBitsAckSn = RLC_STA_PDU_R_BITS_ACKSN_12BITS;
1156       resrvdBitsNackSn = RLC_STA_PDU_R_BITS_NACKSN_12BITS;
1157    }
1158    else if (rbCb->m.amUl.snLen == RLC_AM_CFG_18BIT_SN_LEN)
1159    {
1160       snLen = 18;
1161       resrvdBitsAckSn = RLC_STA_PDU_R_BITS_ACKSN_18BITS;
1162       resrvdBitsNackSn = RLC_STA_PDU_R_BITS_NACKSN_18BITS;
1163    }
1164    else
1165    {
1166       snLen = RLC_SN_LEN;
1167       resrvdBitsAckSn = 0;
1168       resrvdBitsAckSn = 0;
1169    }
1170
1171    pStaPdu->nackCnt = 0;
1172    /* For CPT */
1173    hdrInfo.hdr = hdrInfo.hdr << RLC_CPT_LEN;
1174
1175    /* ACK Sn */
1176    hdrInfo.len = snLen;
1177    rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1178    pStaPdu->ackSn = hdrInfo.val;
1179
1180    //printf ("++++++++++++ 5GNRLOG HNDL STATUS acksn %d : \n",  pStaPdu->ackSn);
1181    /* Check if NACK Exists */
1182    hdrInfo.len = RLC_E1_LEN;
1183    rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1184    e1 = (U8)hdrInfo.val;
1185    RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId, 
1186             "rlcAmmUlHndlStatusPdu: ACK SN = %d UEID:%d CELLID:%d",
1187             pStaPdu->ackSn,
1188             rbCb->rlcId.ueId,
1189             rbCb->rlcId.cellId);
1190
1191    /* Extract the Reserved Bits after ACK SN field */
1192    hdrInfo.len = resrvdBitsAckSn;
1193    rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1194
1195    /* If NACK exists in control PDU */
1196    /* For ACKs and NACKs */
1197    while (e1 && (pStaPdu->nackCnt < RLC_MAX_NACK_CNT))
1198    {
1199       hdrInfo.len = snLen;
1200       rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1201       pStaPdu->nackInfo[pStaPdu->nackCnt].sn = hdrInfo.val;
1202
1203       hdrInfo.len = RLC_E1_LEN;
1204       rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1205       e1 = (U8)hdrInfo.val;
1206
1207       /* Extract e2 */
1208       /* hdrInfo.len = RLC_E1_LEN; --> previusly stored value (for e1) is
1209          already present*/
1210       rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1211       /*  e2 = (U8) hdrInfo.val;*/
1212
1213       /* Store e2 value */
1214       pStaPdu->nackInfo[pStaPdu->nackCnt].isSegment = (U8) hdrInfo.val;
1215
1216       /* Extract e3 : 5GNR */
1217       /* hdrInfo.len = RLC_E1_LEN; --> previusly stored value (for e1) is
1218          already present*/
1219       rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1220       e3 = (U8) hdrInfo.val;
1221
1222       /* Extract Reserved Bits after NACK SN */
1223       hdrInfo.len = resrvdBitsNackSn;
1224       rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1225
1226       /* Test for resegmentation */
1227       if (pStaPdu->nackInfo[pStaPdu->nackCnt].isSegment)
1228       {
1229          hdrInfo.len = RLC_SO_LEN_5GNR; /* 5GNR : SO Len 16 Bits */
1230          rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1231          pStaPdu->nackInfo[pStaPdu->nackCnt].soStart = hdrInfo.val;
1232
1233          rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1234          pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd   = hdrInfo.val;
1235
1236          RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId,
1237                        "rlcAmmUlHndlStatusPdu: soStart and soEnd = %d %d"
1238                        "UEID:%d CELLID:%d",
1239                        pStaPdu->nackInfo[pStaPdu->nackCnt].soStart,
1240                        pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd,      
1241                        rbCb->rlcId.ueId,
1242                        rbCb->rlcId.cellId);
1243       }                                                                
1244       else
1245       {
1246          hdrInfo.len = 0;
1247          pStaPdu->nackInfo[pStaPdu->nackCnt].soStart = 0;
1248          pStaPdu->nackInfo[pStaPdu->nackCnt].soEnd   = 0;
1249
1250       }
1251       /* NACK RANGE Field is SET */
1252       if (e3)
1253       {
1254          /* Extract NACK range field */
1255          hdrInfo.len = RLC_NACK_RANGE_LEN;
1256          rlcAmmExtractElmnt(gCb, cntrlPdu, &hdrInfo);
1257          snRange = (U8)hdrInfo.val;
1258
1259          pStaPdu->nackInfo[pStaPdu->nackCnt].nackRange = snRange;
1260
1261       }
1262       pStaPdu->nackCnt++;
1263    }
1264
1265    gRlcStats.amRlcStats.numULStaPduRcvd++;
1266    gRlcStats.amRlcStats.numULNackInStaPduRcvd += pStaPdu->nackCnt;
1267
1268    /* In case we have reached the MAX NACK CNT, then we should modify the ACK_SN
1269       to the last NACK SN + 1 and discard the original ACK_SN*/
1270    if(pStaPdu->nackCnt == RLC_MAX_NACK_CNT)
1271    {
1272       pStaPdu->ackSn = (pStaPdu->nackInfo[RLC_MAX_NACK_CNT-1].sn + 1) & (rbCb->m.amUl.snModMask);
1273    }
1274
1275
1276    /* Parse & send Status PDU to RLC-DL */
1277    rlcUlUdxStaUpdReq(&(sapCb->pst), sapCb->spId, &rbCb->rlcId, pStaPdu);
1278
1279    RETVOID;
1280 }
1281
1282 /**
1283  * @brief Private handler to release all stored segments
1284  *
1285  * @details
1286  *    Private handler invokded by rlcAmmUlPlacePduInRecBuf to release the
1287  *    stored segements in case a complete PDU is received later.
1288  *
1289  * @param[in]  gCb      RLC instance control block
1290  * @param[in]  recBuf   Buffer that stores a received PDU or segments
1291  *
1292  * @return  Void
1293  *
1294  */
1295 #ifdef ANSI
1296 PRIVATE Void rlcAmmUlRlsAllSegs
1297 (
1298 RlcCb         *gCb,
1299 RlcAmRecBuf   *recBuf
1300 )
1301 #else
1302 PRIVATE Void rlcAmmUlRlsAllSegs(gCb,recBuf)
1303 RlcCb         *gCb;
1304 RlcAmRecBuf   *recBuf;
1305 #endif
1306 {
1307    RlcSeg *seg;
1308
1309    TRC2(rlcAmmUlRlsAllSegs)
1310
1311    RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
1312    while (seg != NULLP)
1313    {
1314       RLC_FREE_BUF_WC(seg->seg);
1315       cmLListDelFrm(&(recBuf->segLst),&(seg->lstEnt));
1316       RLC_FREE_WC(gCb,seg, sizeof(RlcSeg));
1317       RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
1318    }
1319
1320    RETVOID;
1321 }
1322
1323 /**
1324  * @brief Private handler to store the received segment
1325  *
1326  * @details
1327  *    Private handler invokded by rlcAmmUlPlacePduInRecBuf to add a received
1328  *    segment in reception buffer of a RBCB.
1329  *    - It is responsible for detecting duplicate segments
1330  *    - Adding it at appropriate position in the received buffer
1331  *    - Calling ExpByteSeg to set expSo field in the receiver buffer
1332  *
1333  * @param[in]  gCb      RLC instance control block
1334  * @param[in]  rbCb     Radio Bearer Contro Block
1335  * @param[in]  amHdr    AM Header received
1336  * @param[in]  pdu      Buffer received other than the headers
1337  * @param[in]  pduSz    size of the PDU buffer received
1338  *
1339  * @return  Bool
1340  *   -#TRUE  Successful insertion into the receiver buffer
1341  *   -#FALSE Possibly a duplicate segment
1342  */
1343 #ifdef ANSI
1344 PRIVATE Bool rlcAmmAddRcvdSeg
1345 (
1346 RlcCb       *gCb,
1347 RlcUlRbCb   *rbCb,
1348 RlcAmHdr    *amHdr,
1349 Buffer     *pdu,
1350 U16        pduSz
1351 )
1352 #else
1353 PRIVATE Bool rlcAmmAddRcvdSeg(gCb, rbCb, amHdr, pdu, pduSz)
1354 RlcCb       *gCb;
1355 RlcUlRbCb   *rbCb;
1356 RlcAmHdr    *amHdr;
1357 Buffer     *pdu;
1358 U16        pduSz;
1359 #endif
1360 {
1361    RlcAmRecBuf   *recBuf = NULLP;
1362    RlcSeg        *seg;
1363    RlcSeg        *tseg;
1364    U16          soEnd;       /* Holds the SoEnd of received segment */
1365    U16          expSo = 0;   /* Expected SO */
1366
1367    TRC2(rlcAmmAddRcvdSeg)
1368
1369    soEnd = amHdr->so + pduSz - 1;
1370    recBuf =  rlcUtlGetRecBuf(AMUL.recBufLst, amHdr->sn);
1371
1372    if (NULLP == recBuf)
1373    {
1374       RLC_ALLOC(gCb,recBuf, sizeof(RlcAmRecBuf));
1375 #if (ERRCLASS & ERRCLS_ADD_RES)
1376       if (recBuf == NULLP)
1377       {
1378          RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
1379                   "Memory allocation failed UEID:%d CELLID:%d",
1380                   rbCb->rlcId.ueId,
1381                   rbCb->rlcId.cellId);
1382
1383          RLC_FREE_BUF(pdu);
1384          return (FALSE);
1385       }
1386 #endif /* ERRCLASS & ERRCLS_RES */
1387       rlcUtlStoreRecBuf(AMUL.recBufLst, recBuf, amHdr->sn);
1388    }
1389    else
1390    {
1391       if (recBuf->allRcvd == TRUE)
1392       {
1393          RLC_FREE_BUF(pdu);
1394          return (FALSE);
1395       }
1396    }
1397                         
1398    recBuf->isDelvUpperLayer = FALSE;
1399    /* kw003.201 - Move past the segments that are different than the */
1400    /*             one received.                                      */
1401    RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
1402    while ((seg != NULLP) && (seg->amHdr.so < amHdr->so))
1403    {
1404       expSo = seg->amHdr.so + seg->segSz;
1405       RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
1406    }
1407
1408    /* The received segment should start after the end of previous seg */
1409    if (expSo > amHdr->so)
1410    {
1411       /* This is a duplicate segment */
1412       gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
1413       RLC_FREE_BUF(pdu);
1414       return (FALSE);
1415    }
1416
1417    if ((seg) && (seg->amHdr.so <= soEnd))
1418    {
1419       /* This is a duplicate segment */
1420       gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
1421       RLC_FREE_BUF(pdu);
1422       return (FALSE);
1423    }
1424
1425    /* If we have come this far, we have to add this segment to the   */
1426    /* reception buffer as we either have eliminated duplicates or    */
1427    /* have found none.                                               */
1428    RLC_ALLOC_WC(gCb,tseg, sizeof(RlcSeg));
1429 #if (ERRCLASS & ERRCLS_ADD_RES)
1430    if (tseg == NULLP)
1431    {
1432       RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId, 
1433                "Memory allocation failed UEID:%d CELLID:%d",
1434                rbCb->rlcId.ueId,
1435                rbCb->rlcId.cellId);
1436       RLC_FREE_BUF(pdu);
1437       return (FALSE);
1438    }
1439 #endif /* ERRCLASS & ERRCLS_RES */
1440
1441    tseg->seg = pdu;
1442    tseg->segSz = pduSz;
1443    RLC_MEM_CPY(&tseg->amHdr, amHdr, sizeof(RlcAmHdr));
1444    recBuf->amHdr.si = amHdr->si;
1445    recBuf->amHdr.sn = amHdr->sn;
1446    tseg->soEnd = soEnd;
1447    if (seg == NULLP)
1448    {
1449       cmLListAdd2Tail(&recBuf->segLst, &tseg->lstEnt);
1450    }
1451    else
1452    {
1453       recBuf->segLst.crnt = &seg->lstEnt;
1454       cmLListInsCrnt(&recBuf->segLst, &tseg->lstEnt);
1455    }
1456    tseg->lstEnt.node = (PTR)tseg;
1457    rlcAmmUpdExpByteSeg(gCb,&AMUL,tseg);
1458
1459    return (TRUE);
1460 }
1461
1462 /**
1463  * @brief Private handler to place the PDU in the reception buffer
1464  *
1465  * @details
1466  *    This function checks if the received PDU's SN falls within the
1467  *    receiving window, after which it places the same in the reception
1468  *    buffer if its not a duplicate.
1469  *
1470  * @param[in]  gCb   RLC instance control block
1471  * @param[in]  pdu   Received PDU
1472  * @param[in]  rbCb  Uplink AM Radio Bearer
1473  * @param[out] amUl  AM UL Info
1474  *
1475  * @return Bool
1476  *     -# TRUE
1477  *     -# FALSE
1478  *
1479  */
1480 #ifdef ANSI
1481 PRIVATE Bool rlcAmmUlPlacePduInRecBuf
1482 (
1483 RlcCb       *gCb,
1484 Buffer     *pdu,
1485 RlcUlRbCb   *rbCb,
1486 RlcAmHdr    *amHdr
1487 )
1488 #else
1489 PRIVATE Bool rlcAmmUlPlacePduInRecBuf(gCb, pdu, rbCb, amHdr)
1490 RlcCb       *gCb;
1491 Buffer     *pdu;
1492 RlcUlRbCb   *rbCb;
1493 RlcAmHdr    *amHdr;
1494 #endif
1495 {
1496    RlcSn     sn;
1497    MsgLen   pduSz;
1498    RlcAmUl   *amUl = &(rbCb->m.amUl);
1499
1500    TRC2(rlcAmmUlPlacePduInRecBuf)
1501
1502
1503    sn = amHdr->sn;
1504    SFndLenMsg(pdu, &pduSz);
1505
1506    gCb->genSts.bytesRecv += pduSz;
1507    gRlcStats.amRlcStats.numRlcAmCellSduBytesRx += pduSz; 
1508    if (!RLC_AM_CHK_SN_WITHIN_RECV_WINDOW(sn, amUl))
1509    {
1510       gRlcStats.amRlcStats.numRlcAmCellDropOutWinRx++;
1511       RLOG_ARG3(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId,
1512                     "rlcAmmUlPlacePduInRecBuf: SN  %d outside the window"
1513                     "UEID:%d CELLID:%d",
1514                     sn,
1515                     rbCb->rlcId.ueId,
1516                     rbCb->rlcId.cellId);
1517
1518       gCb->genSts.unexpPdusRecv++;
1519       RLC_FREE_BUF(pdu);
1520       return (FALSE);
1521    }
1522
1523    if (amHdr->si == 0)
1524    {
1525       RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
1526
1527       /* We received a complete PDU. Either we already have it, in which */
1528       /* case we just ignore the new PDU and discard it. Otherwise,      */
1529       /* store the received PDU in the reception buffer                  */
1530       if (NULLP == recBuf)
1531       {
1532          RLC_ALLOC(gCb, recBuf, sizeof(RlcAmRecBuf));
1533 #if (ERRCLASS & ERRCLS_ADD_RES)
1534          if (recBuf == NULLP)
1535          {
1536             RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
1537                      "Memory allocation failed UEID:%d CELLID:%d",
1538                      rbCb->rlcId.ueId,
1539                      rbCb->rlcId.cellId);
1540             RLC_FREE_BUF(pdu);
1541             return (FALSE);
1542          }
1543 #endif /* ERRCLASS & ERRCLS_RES */
1544          rlcUtlStoreRecBuf(AMUL.recBufLst, recBuf, sn);
1545       }
1546       else if (recBuf->allRcvd != TRUE)
1547       {
1548          rlcAmmUlRlsAllSegs(gCb,recBuf);
1549       }
1550       else
1551       {
1552          gRlcStats.amRlcStats.numRlcAmCellDupPduRx++;
1553          gCb->genSts.unexpPdusRecv++;
1554          RLC_FREE_BUF(pdu);
1555          return (FALSE);
1556       }
1557       recBuf->isDelvUpperLayer = FALSE;
1558       recBuf->pdu = pdu;
1559       recBuf->pduSz = pduSz;
1560       recBuf->allRcvd = TRUE;
1561       gRlcStats.amRlcStats.numRlcAmCellSduRx++;
1562       RLC_MEM_CPY(&recBuf->amHdr, amHdr, sizeof(RlcAmHdr));
1563       return (TRUE);
1564    }
1565    else
1566    {
1567       /* We received a segment. We need to add that to the existing */
1568       /* segments, if any.                                          */
1569       return (rlcAmmAddRcvdSeg(gCb,rbCb, amHdr, pdu, pduSz));
1570    }
1571 }
1572
1573 /**
1574  * @brief Private handler to trigger status report
1575  *
1576  * @details
1577  *    Private handler invokded by rlcAmmProcessPdus to check if the
1578  *    status report need to be sent, and update the status trigger
1579  *    flag accordingly based on status prohibit timer.
1580  *
1581  *    - Check if the received pdu's sn is less than rxHighestStatus, set the
1582  *      staTrg flag.
1583  *    - If staProhTmr is not running, calculate cntrlBo, else it'll be
1584  *      updated at the expiry of staProhTmr.
1585  *    - Expiry of reOrdTmr also will set staTrg flag.
1586  *
1587  * @param[in]  gCb       RLC instance control block
1588  * @param[in]  rbCb      Uplink RB control block
1589  * @param[in]  sn        Sequence number of the pdu based on which to check if
1590  *                       status needs to be triggered
1591  * @param[in]  discFlg   Whether this pdu was discarded or not
1592  *
1593  * @return  Void
1594  *
1595  */
1596 #ifdef ANSI
1597 PRIVATE Void rlcAmmTriggerStatus
1598 (
1599 RlcCb       *gCb,
1600 RlcUlRbCb   *rbCb,
1601 RlcSn       sn,
1602 Bool       discFlg
1603 )
1604 #else
1605 PRIVATE Void rlcAmmTriggerStatus(gCb,rbCb, sn, discFlg)
1606 RlcCb       *gCb;
1607 RlcUlRbCb   *rbCb;
1608 RlcSn       sn;
1609 Bool       discFlg;
1610 #endif
1611 {
1612    Bool     tmrRunning;
1613    RlcSn     tSn;
1614    RlcSn     tVrMr;
1615    RlcSn     trxHighestStatus;
1616    RlcAmUl   *amUl = &(rbCb->m.amUl);
1617
1618    TRC2(rlcAmmTriggerStatus)
1619
1620
1621    MODAMR(amUl->vrMr, tVrMr, amUl->rxNext, amUl->snModMask);
1622    MODAMR(amUl->rxHighestStatus, trxHighestStatus, amUl->rxNext, amUl->snModMask);
1623    MODAMR(sn , tSn, amUl->rxNext, amUl->snModMask);
1624
1625    /* kw005.201 Product CR ccpu00117114       *
1626     * The "=" in the 2nd condition is removed */
1627    if ((discFlg) || (tSn < trxHighestStatus) || (tSn >= tVrMr))
1628    {
1629       RLOG_ARG2(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId, 
1630                "rlcAmmTriggerStatus: Set Status Trigger UEID:%d CELLID:%d",
1631                      rbCb->rlcId.ueId,
1632                      rbCb->rlcId.cellId);
1633
1634       amUl->staTrg = TRUE;
1635       amUl->gatherStaPduInfo = FALSE;
1636
1637       /* Check if staProhTmr is running */
1638       tmrRunning = rlcChkTmr(gCb,(PTR) rbCb, RLC_EVT_AMUL_STA_PROH_TMR);
1639
1640       if (!tmrRunning)
1641       {
1642          amUl->gatherStaPduInfo = TRUE;
1643       }
1644    }
1645
1646    RETVOID;
1647 }
1648
1649 /**
1650  * @brief Private handler to reassemble from a segment or a PDU
1651  *
1652  * @details
1653  *    Private handler invokded by kwAmmReassembleSdus with either a
1654  *    PDU or a segment of a PDU. This is also called in the case of
1655  *    reestablishment and hence out of sequence joining is also to
1656  *    be supported
1657  *
1658  *
1659  * @param[in]  gCb     RLC instance control block
1660  * @param[in]  rbCb    Uplink RB control block
1661  * @param[in]  amHdr   AM header received for this segment/PDU
1662  * @param[in]  pdu     PDU to be reassembled
1663  *
1664  * @return  Void
1665  *
1666  */
1667 #ifdef ANSI
1668 PRIVATE Void rlcAmmProcPduOrSeg
1669 (
1670 RlcCb       *gCb,
1671 RlcUlRbCb   *rbCb,
1672 RlcAmHdr    *amHdr,
1673 Buffer     *pdu
1674 )
1675 #else
1676 PRIVATE Void rlcAmmProcPduOrSeg(gCb, rbCb, amHdr, pdu)
1677 RlcCb       *gCb;
1678 RlcUlRbCb   *rbCb;
1679 RlcAmHdr    *amHdr;
1680 Buffer     *pdu;
1681 #endif
1682 {
1683
1684    TRC2(rlcAmmProcPduOrSeg)
1685
1686    if ((AMUL.expSn != amHdr->sn) || (AMUL.expSo != amHdr->so))
1687    {
1688       /* Release the existing partial SDU as we have PDUs or */
1689       /* segments that are out of sequence                   */
1690       rbCb->m.amUl.isOutOfSeq = TRUE;
1691       RLC_FREE_BUF(AMUL.partialSdu);
1692    }
1693
1694    //if (amHdr->fi & RLC_FI_FIRST_SEG)
1695    if (amHdr->si == 0x01)
1696    {/* first Segment of the SDU */
1697       if (AMUL.partialSdu != NULLP)
1698       { /* Some old SDU may be present */
1699          RLC_FREE_BUF_WC(AMUL.partialSdu);
1700       }
1701       AMUL.partialSdu = pdu;
1702       pdu = NULLP;
1703    }
1704    else if(amHdr->si == 0x03)
1705    {/* Middle or last segment of the SUD */
1706       SCatMsg(AMUL.partialSdu,pdu, M1M2);
1707       RLC_FREE_BUF_WC(pdu);
1708       pdu = NULLP;
1709    }
1710    else if (amHdr->si ==  0x02)
1711    {
1712       SCatMsg(pdu,AMUL.partialSdu,M2M1);
1713       RLC_FREE_BUF_WC(AMUL.partialSdu);
1714    }
1715
1716    if (pdu != NULLP)
1717    {
1718       AMUL.partialSdu = NULLP;
1719       rlcUtlSndDatInd(gCb,rbCb, pdu);
1720    }
1721
1722    RETVOID;
1723 }
1724
1725 /**
1726  *
1727  * @brief Private handler to reassemble SDUs
1728  *
1729  * @details
1730  *    Private handler invokded by rlcAmmProcessPdus with the PDU
1731  *    from the reception buffer in sequence to reassemble SDUs and
1732  *    send it to PDCP.
1733  *
1734  *        - With the stored header info, FI and LSF segment / concatenate
1735  *          PDUs or byte segments of PDUs to get the associated SDU.
1736  *
1737  * @param[in]  rbCb     RB control block
1738  * @param[in]  pdu      PDU to be reassembled
1739  *
1740  *  @return  S16
1741  *      -# ROK
1742  *      -# RFAILED
1743  *
1744  */
1745 #ifdef ANSI
1746 PRIVATE S16 rlcAmmUlReassembleSdus
1747 (
1748 RlcCb         *gCb,
1749 RlcUlRbCb     *rbCb,
1750 RlcAmRecBuf   *recBuf
1751 )
1752 #else
1753 PRIVATE S16 rlcAmmUlReassembleSdus(gCb, rbCb, recBuf)
1754 RlcCb         *gCb;
1755 RlcUlRbCb     *rbCb;
1756 RlcAmRecBuf   *recBuf;
1757 #endif
1758 {
1759    RlcSeg        *seg;
1760
1761    TRC2(rlcAmmUlReassembleSdus)
1762    //if (recBuf->amHdr.rf == 0)
1763    if (recBuf->amHdr.si == 0)
1764    {
1765       /* This is a PDU */
1766       rlcAmmProcPduOrSeg(gCb,rbCb, &recBuf->amHdr, recBuf->pdu);
1767       /* Assign NULLP to recBuf->pdu as this PDU is sent to PDCP */
1768       recBuf->pdu = NULLP;
1769       AMUL.expSn = (recBuf->amHdr.sn + 1) & (AMUL.snModMask); /* MOD 1024 */
1770       AMUL.expSo = 0;
1771    }
1772    else
1773    {
1774       /* This is a set of segments */
1775       RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
1776       AMUL.expSn = recBuf->amHdr.sn;
1777       AMUL.expSo = 0;
1778       while(seg)
1779       {
1780          rlcAmmProcPduOrSeg(gCb,rbCb, &seg->amHdr, seg->seg);
1781          AMUL.expSo = seg->soEnd + 1;
1782
1783          cmLListDelFrm(&(recBuf->segLst),&(seg->lstEnt));
1784          RLC_FREE_WC(gCb, seg, sizeof(RlcSeg));
1785
1786          RLC_LLIST_FIRST_SEG(recBuf->segLst, seg);
1787       }
1788       AMUL.expSn = (recBuf->amHdr.sn + 1) & (AMUL.snModMask); /* MOD 1024 */
1789       AMUL.expSo = 0;
1790    }
1791
1792    return ROK;
1793 }
1794
1795 /**
1796  * @brief   Handler to process the re-establishment request received from UIM
1797  *
1798  * @param[in] gCb         RLC instance control block
1799  * @param[in] rlcId       RLC identifier
1800  * @param[in] sendReEst   Whether to send back restablishment complete or not
1801  * @param[in] rbCb        Uplink RB control block
1802  *
1803  * @return  Void
1804  *
1805  */
1806 #ifdef ANSI
1807 Void rlcAmmUlReEstablish
1808 (
1809 RlcCb         *gCb,
1810 CmLteRlcId   rlcId,
1811 Bool         sendReEst,
1812 RlcUlRbCb     *rbCb
1813 )
1814 #else
1815 Void rlcAmmUlReEstablish(gCb, rlcId, sendReEst, rbCb)
1816 RlcCb         *gCb;
1817 CmLteRlcId   rlcId;
1818 Bool         sendReEst;
1819 RlcUlRbCb     *rbCb;
1820 #endif
1821 {
1822    RlcSn   sn;
1823    RlcSn   mSn;
1824    RlcSn   mVrMr;
1825
1826 #ifndef KW_PDCP
1827    RlcKwuSapCb *rlcKwuSap;
1828 #endif
1829    RlcAmRecBuf   *recBuf = NULLP;
1830
1831    TRC2(rlcAmmUlReEstablish);
1832
1833
1834    sn = AMUL.rxNext;
1835
1836    MODAMR(AMUL.vrMr, mVrMr, AMUL.rxNext, AMUL.snModMask);
1837    MODAMR(sn, mSn, AMUL.rxNext, AMUL.snModMask);
1838
1839    /* Reassemble SDUs from PDUs with SN less than upper edge of the window */
1840    while (mSn < mVrMr)
1841    {
1842       recBuf = rlcUtlGetRecBuf(AMUL.recBufLst, sn);
1843       if (NULLP != recBuf)
1844       {
1845          if (recBuf->allRcvd == TRUE)
1846          {
1847             rlcAmmUlReassembleSdus(gCb,rbCb, recBuf);
1848          }
1849          else
1850          {
1851             /* Remove PDU and segments */
1852             if(recBuf->pdu)
1853             {
1854                RLC_FREE_BUF_WC(recBuf->pdu);
1855             }
1856             /* Release all the segments*/
1857             rlcAmmUlRlsAllSegs(gCb,recBuf);
1858          }
1859          rlcUtlDelRecBuf(AMUL.recBufLst, recBuf, gCb);
1860       }
1861       sn = (sn + 1) & (AMUL.snModMask); /* MOD 1024 */
1862       MODAMR(sn, mSn, AMUL.rxNext, AMUL.snModMask);
1863    }
1864    /* Discard remaining PDUs and bytesegments in recBuf */
1865
1866    /* Stop all timers and reset variables */
1867    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_AMUL_REORD_TMR))
1868    {
1869        rlcStopTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
1870    }
1871    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_AMUL_STA_PROH_TMR))
1872    {
1873        rlcStopTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_STA_PROH_TMR);
1874    }
1875
1876    AMUL.rxNext  = 0;
1877    AMUL.rxNextHighestRcvd  = 0;
1878    AMUL.rxNextStatusTrig  = 0;
1879    rbCb->m.amUl.vrMr = (rbCb->m.amUl.rxNext + RLC_AM_GET_WIN_SZ(rbCb->m.amUl.snLen)) & (rbCb->m.amUl.snModMask);
1880    AMUL.rxHighestStatus = 0;
1881    AMUL.staTrg  = FALSE;
1882    AMUL.gatherStaPduInfo = FALSE;
1883    AMUL.expSn = 0;
1884    AMUL.expSo = 0;
1885    if (AMUL.partialSdu != NULLP)
1886    {
1887      RLC_FREE_BUF(AMUL.partialSdu);
1888    }
1889    rlcKwuSap = gCb->u.ulCb->rlcKwuUlSap + RLC_UI_PDCP;
1890
1891    if(sendReEst)
1892    {
1893       RlcUiKwuReEstCmpInd(&rlcKwuSap->pst, rlcKwuSap->suId, rlcId);
1894       rbCb->m.amUl.isOutOfSeq = FALSE;
1895    }
1896
1897    RETVOID;
1898 }
1899
1900 /**
1901  * @brief  Handler for reorder timer expiry
1902  *
1903  * @details
1904  *    This function is used to handle events upon expiry of reorder timer
1905  *
1906  *  @param[in] gCb   RLC instance control block
1907  *  @param[in] rbCb  RB control block
1908  *
1909  *  @return  Void
1910  *
1911  */
1912
1913 #ifdef ANSI
1914 Void rlcAmmReOrdTmrExp
1915 (
1916 RlcCb        *gCb,
1917 RlcUlRbCb    *rbCb
1918 )
1919 #else
1920 Void rlcAmmReOrdTmrExp(rbCb)
1921 RlcCb        *gCb;
1922 RlcUlRbCb    *rbCb;
1923 #endif
1924 {
1925    RlcAmUl *amUl = &(rbCb->m.amUl);
1926    RlcSn sn;
1927    RlcSn mSn;
1928    RlcSn mVrMr;
1929    RlcSn mrxHighestStatus;
1930    RlcSn mrxNextHighestRcvd;
1931    Bool tmrRunning = FALSE;
1932    RlcAmRecBuf   *recBuf = NULLP;
1933
1934    TRC2(rlcAmmReOrdTmrExp);
1935
1936
1937    /* Update rxHighestStatus */
1938    sn = amUl->rxNextStatusTrig;
1939
1940    MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
1941    MODAMR(amUl->vrMr, mVrMr, amUl->rxNext, amUl->snModMask);
1942    recBuf = rlcUtlGetRecBuf(AMUL.recBufLst, sn);
1943
1944    while (mSn < mVrMr)
1945    {
1946       if ((recBuf == NULLP) ||
1947           ((recBuf != NULLP) && (!recBuf->allRcvd)) )
1948       {
1949          amUl->rxHighestStatus = sn;
1950          amUl->staTrg = TRUE;
1951          amUl->gatherStaPduInfo = FALSE;
1952
1953          /* Check if staProhTmr is running */
1954          tmrRunning = rlcChkTmr(gCb,(PTR) rbCb, RLC_EVT_AMUL_STA_PROH_TMR);
1955
1956          if (!tmrRunning)
1957          {
1958             gRlcStats.amRlcStats.numULReOrdTimerExpires++;
1959             amUl->gatherStaPduInfo = TRUE;
1960             rlcAmmUlAssembleCntrlInfo(gCb, rbCb);
1961          }
1962
1963          break;
1964       }
1965       sn = (sn + 1) & (amUl->snModMask); 
1966       MODAMR(sn, mSn, amUl->rxNext, amUl->snModMask);
1967    }
1968
1969    /* Update rxNextStatusTrig */
1970    MODAMR(amUl->rxNextHighestRcvd, mrxNextHighestRcvd, amUl->rxNext, amUl->snModMask);
1971    MODAMR(amUl->rxHighestStatus, mrxHighestStatus, amUl->rxNext, amUl->snModMask);
1972    if (mrxNextHighestRcvd > mrxHighestStatus)
1973    {
1974       rlcStartTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
1975       amUl->rxNextStatusTrig = amUl->rxNextHighestRcvd;
1976    }
1977
1978    RETVOID;
1979 } /* rlcAmmReOrdTmrExp */
1980
1981 /**
1982  * @brief  Handler for status prohibit timer expiry
1983  *
1984  * @details
1985  *    This function is used to handle events upon expiry of status prohibit
1986  *    timer
1987  *
1988  *  @param[in] gCb   RLC instance control block
1989  *  @param[in] rbCb   RB control block
1990  *
1991  *  @return  Void
1992  *
1993  */
1994
1995 #ifdef ANSI
1996 Void rlcAmmStaProTmrExp
1997 (
1998 RlcCb        *gCb,
1999 RlcUlRbCb    *rbCb
2000 )
2001 #else
2002 Void rlcAmmStaProTmrExp(gCb, rbCb)
2003 RlcCb        *gCb;
2004 RlcUlRbCb    *rbCb;
2005 #endif
2006 {
2007    RlcAmUl *amUl = &(rbCb->m.amUl);
2008
2009    TRC2(rlcAmmStaProTmrExp);
2010
2011
2012    amUl->gatherStaPduInfo = FALSE;
2013
2014    if (amUl->staTrg == TRUE)
2015    {
2016       amUl->gatherStaPduInfo = TRUE;
2017       /* kw002.201 : Sending StaRsp after StaProhibit tmr expiry */
2018       rlcAmmUlAssembleCntrlInfo(gCb,rbCb);
2019    }
2020
2021    RETVOID;
2022 } /* rlcAmmStaProTmrExp */
2023
2024 /**
2025  * @brief  Handler to extract an element of AM Header
2026  *
2027  * @details
2028  *    This function is used to extract an element of AM header.
2029  *
2030  * @param[in]     pdu      The pdu to be decoded
2031  * @param[in,out] hdrInfo  Container to hold the decoded info
2032  *
2033  * @return Void
2034  *
2035  */
2036
2037 #ifdef ANSI
2038 PRIVATE Void rlcAmmExtractElmnt
2039 (
2040 RlcCb       *gCb,
2041 Buffer     *pdu,
2042 RlcExtHdr   *hdrInfo
2043 )
2044 #else
2045 PRIVATE Void rlcAmmExtractElmnt(gCb, pdu, hdrInfo)
2046 RlcCb       *gCb;
2047 Buffer     *pdu;
2048 RlcExtHdr   *hdrInfo;
2049 #endif
2050 {
2051    U8   hdr;
2052    U8   pLen = hdrInfo->pLen;
2053    U8   len  = (U8)hdrInfo->len;
2054    U32  val;
2055    U8   tHdr;
2056    U8   fLen;
2057    U8   rLen;
2058    /* U8   rLen1 = 0; */
2059    U16  tVal;
2060
2061    TRC2(rlcAmmExtractElmnt);
2062
2063    hdr = hdrInfo->hdr;
2064
2065    if (pLen == 0)
2066    {
2067       SRemPreMsg(&hdr, pdu);
2068       pLen = 8;
2069    }
2070    tHdr = hdr;
2071    if (len <= 8)
2072    {
2073       val = tHdr >> (RLC_BYTE_LEN - (len));
2074       hdr =  hdr << len;
2075       pLen -= len;
2076    }
2077    else /*if (len > 8) */
2078    {
2079       fLen = pLen;
2080       val = tHdr;
2081       val = val >> (RLC_BYTE_LEN - fLen);
2082       val = val << (len - fLen);
2083       rLen = len - fLen;
2084       SRemPreMsg(&hdr, pdu);
2085       tHdr = hdr;
2086       if (rLen <= 8)
2087       {
2088          hdr = hdr >> (RLC_BYTE_LEN - rLen);
2089          val = val | hdr;
2090          hdr = tHdr << rLen;
2091          pLen = (RLC_BYTE_LEN - rLen);
2092       }
2093       else
2094       {
2095         rLen = rLen - RLC_BYTE_LEN;
2096         tVal = hdr;
2097         tVal = tVal << rLen;
2098         val = val | tVal;
2099
2100         SRemPreMsg(&hdr, pdu);
2101         tHdr = hdr;
2102         hdr = hdr >> (RLC_BYTE_LEN - rLen);
2103         val = val | hdr;
2104         hdr = tHdr << rLen;
2105         pLen = (RLC_BYTE_LEN - rLen);
2106       }
2107    }
2108
2109    hdrInfo->pLen = pLen;
2110    hdrInfo->hdr = hdr;
2111    hdrInfo->val = val;
2112
2113    RETVOID;
2114 }
2115
2116 /**
2117  * @brief  Handler to updated expected byte seg
2118  *
2119  * @details
2120  *    This function is used to update expected byte segment. The next segment
2121  *    expected is indicated by the SO of the segment which is expected. Intially
2122  *    the segment with SO 0 is expected and then in order. When all the segments
2123  *    are received (which would happen when an expected SO is encountered
2124  *    with LSF set) the allRcvd flag is set to TRUE
2125  *
2126  * @param[in]  gCb   RLC instance control block
2127  * @param[in]  amUl  AM Uplink Control Block
2128  * @param[in]  seg   Newly received segment
2129  *
2130  * @return Void
2131  *
2132  */
2133
2134 #ifdef ANSI
2135 PRIVATE Void rlcAmmUpdExpByteSeg
2136 (
2137 RlcCb     *gCb,
2138 RlcAmUl   *amUl,
2139 RlcSeg    *seg
2140 )
2141 #else
2142 PRIVATE Void rlcAmmUpdExpByteSeg(gCb, amUl, seg)
2143 RlcCb     *gCb;
2144 RlcAmUl   *amUl;
2145 RlcSeg    *seg;
2146 #endif
2147 {
2148    U16    newExpSo; /* The new expected SO */
2149    RlcSn   sn = seg->amHdr.sn;
2150    Bool   lstRcvd=FALSE;
2151    RlcAmRecBuf *recBuf = NULLP;
2152    
2153    TRC2(rlcAmmUpdExpByteSeg);
2154
2155
2156    recBuf = rlcUtlGetRecBuf(amUl->recBufLst, sn);
2157    if ((recBuf == NULLP) || (recBuf && (seg->amHdr.so != recBuf->expSo)))
2158    {
2159       RETVOID;
2160    }
2161
2162    newExpSo   = seg->soEnd + 1;
2163    recBuf->expSo = newExpSo;
2164    //lstRcvd = seg->amHdr.lsf;
2165    if(seg->amHdr.si == 0x2)
2166    {  
2167       lstRcvd = TRUE;
2168    } 
2169    /* kw003.201 - This should update seg with the one after newSeg */
2170    RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
2171    while(seg)
2172    {
2173       /* keep going ahead as long as the expectedSo match with the header so
2174          else store the expSo for later checking again */
2175       if(seg->amHdr.si == 0x2)
2176       {  
2177          lstRcvd = TRUE;
2178       } 
2179       if (seg->amHdr.so == newExpSo)
2180       {
2181          newExpSo = seg->soEnd + 1;
2182          recBuf->expSo = newExpSo;
2183          //lstRcvd = seg->amHdr.lsf;
2184          RLC_LLIST_NEXT_SEG(recBuf->segLst, seg);
2185       }
2186       else
2187       {
2188          recBuf->expSo = newExpSo;
2189          RETVOID;
2190       }
2191    }
2192    if (lstRcvd == TRUE)
2193    {
2194       recBuf->allRcvd = TRUE;
2195       gRlcStats.amRlcStats.numRlcAmCellSduRx++;
2196    }
2197
2198    RETVOID;
2199 }
2200
2201 /**
2202  * @brief
2203  *   Function to release/free the Acknowledged Mode Module  RbCb buffers
2204  *
2205  * @details
2206  *   This primitive Frees the AM RbCb transmission Buffer, retransmission
2207  *   Buffer and reciption Buffers
2208  *
2209  * @param [in]   gCb   - RLC instance Control Block
2210  * @param [in]   rbCb  - RB Control Block
2211  *
2212  * @return   void
2213  */
2214 #ifdef ANSI
2215 Void rlcAmmFreeUlRbCb
2216 (
2217 RlcCb       *gCb,
2218 RlcUlRbCb   *rbCb
2219 )
2220 #else
2221 Void rlcAmmFreeUlRbCb(gCb,rbCb)
2222 RlcCb       *gCb;
2223 RlcUlRbCb   *rbCb;
2224 #endif
2225 {
2226    RlcSn         curSn = 0;           /* Sequence number of PDU */
2227    RlcSn         windSz;              /* PDU window size */
2228    RlcAmRecBuf *recBuf = NULLP;
2229
2230    TRC2(rlcAmmFreeUlRbCb)
2231
2232
2233    windSz  =  (RLC_AM_GET_WIN_SZ(rbCb->m.amUl.snLen)) << 1;
2234
2235    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_AMUL_REORD_TMR))
2236    {
2237       rlcStopTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_REORD_TMR);
2238    }
2239    if(TRUE == rlcChkTmr(gCb,(PTR)rbCb,RLC_EVT_AMUL_STA_PROH_TMR))
2240    {
2241       rlcStopTmr(gCb,(PTR)rbCb, RLC_EVT_AMUL_STA_PROH_TMR);
2242    }
2243
2244
2245    /* on the first loop winSz is always greater than zero
2246     while( ( curSn < windSz ) hence changing to do while */
2247    do
2248    {
2249       recBuf = rlcUtlGetRecBuf(rbCb->m.amUl.recBufLst, curSn);
2250       if ( recBuf != NULLP )
2251       {
2252          if (recBuf->pdu != NULLP)
2253          {
2254             RLC_FREE_BUF_WC(recBuf->pdu);
2255          }
2256          /* Release all the segments */
2257          rlcAmmUlRlsAllSegs(gCb,recBuf);
2258          rlcUtlDelRecBuf(rbCb->m.amUl.recBufLst, recBuf, gCb);
2259       }
2260       curSn++;
2261    }while ( curSn < windSz );
2262
2263 #ifndef LTE_TDD 
2264       RLC_FREE_WC(gCb,rbCb->m.amUl.recBufLst, (RLC_RCV_BUF_BIN_SIZE * sizeof(CmLListCp)));
2265       rbCb->m.amUl.recBufLst = NULLP;
2266 #endif
2267
2268    if(rbCb->m.amUl.partialSdu != NULLP)
2269    {
2270       RLC_FREE_BUF_WC(rbCb->m.amUl.partialSdu);
2271    }
2272    RETVOID;
2273 } /* rlcAmmFreeUlRbCb */
2274
2275
2276 /*@}*/
2277
2278 \f
2279 /********************************************************************30**
2280
2281          End of file
2282 **********************************************************************/