Merge "Added a new Flag ODU_LWR_MAC_DEBUG in the code"
[o-du/l2.git] / src / 5gnrsch / rg_sch_dhm.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     LTE-MAC layer
22   
23      Type:     C source file
24   
25      Desc:     C source code for Entry point fucntions
26   
27      File:     rg_sch_dhm.c
28   
29 **********************************************************************/
30
31 /** @file rg_sch_dhm.c
32 @brief APIs related to Downlink HARQ for the scheduler.
33 */
34
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_FILE_ID=242;
37 static int RLOG_MODULE_ID=4096;
38
39 /* header include files -- defines (.h) */
40 #include "common_def.h"
41 #include "lrg.h"
42 #include "rgr.h"
43 #include "rgm.h"
44 #include "tfu.h"
45 #include "rg_env.h"
46 #include "rg_sch_err.h"
47 #include "rg_sch_inf.h"         /* typedefs for Scheduler */
48 #include "rg_sch.h"
49 #include "rg_sch_cmn.h"
50 #include "rl_interface.h"
51 #include "rl_common.h"
52
53 /* header/extern include files (.x) */
54 #include "lrg.x"
55 #include "rgr.x"
56 #include "rgm.x"
57 #include "tfu.x"
58 #include "rg_sch_inf.x"         /* typedefs for Scheduler */
59 #include "rg_sch.x"
60 #include "rg_sch_cmn.x"
61
62 #ifdef RGSCH_SPS_STATS
63 extern U32 rgNumSPSSchedDropMaxRetx;
64 extern U32 rgNumActDtx;
65 #endif
66 U32  nackSf[10];
67
68
69
70 #ifdef MAC_SCH_STATS
71 RgSchNackAckStats hqFailStats;
72 RgSchHqRetxStats  hqRetxStats;
73 #endif /* MAC_SCH_STATS */
74 //Chandan Stats Collection
75 #ifdef DLHQ_STATS
76 U32 statsCnt;
77 RgSchDlHqStats dlHqStats[10000] = {{0,0,0}};
78 #endif
79
80 #ifdef TFU_TDD
81 /* For special bundling case: convert numOfAcks to ACK/NACK
82  * The below table derives the HARQ aknowledgement as ACK or NACK using the 
83  * number of transmission done and the feedback value received
84  * The below table is based on Table 7.3-X from 36.213 and 
85  * table 79 from FAPIv1.1 doc
86  */
87 U8 rgSchNumOfAcksToAckNack[RG_SCH_MAX_NUM_EXPECTED_ACKS][RG_SCH_NUM_FDBK_VALUE] = {
88 {TFU_HQFDB_ACK,     TFU_HQFDB_NACK,    TFU_HQFDB_NACK},
89 {TFU_HQFDB_NACK,    TFU_HQFDB_ACK,     TFU_HQFDB_NACK},
90 {TFU_HQFDB_NACK,    TFU_HQFDB_NACK,    TFU_HQFDB_ACK},
91 {TFU_HQFDB_ACK,     TFU_HQFDB_NACK,    TFU_HQFDB_NACK},
92 {TFU_HQFDB_NACK,    TFU_HQFDB_ACK,     TFU_HQFDB_NACK},
93 {TFU_HQFDB_NACK,    TFU_HQFDB_NACK,    TFU_HQFDB_ACK},
94 {TFU_HQFDB_ACK,     TFU_HQFDB_NACK,    TFU_HQFDB_NACK},
95 {TFU_HQFDB_NACK,    TFU_HQFDB_ACK,     TFU_HQFDB_NACK},
96 {TFU_HQFDB_NACK,    TFU_HQFDB_NACK,    TFU_HQFDB_ACK}
97 };
98 #endif
99
100 /* local typedefs */
101  
102 /* local externs */
103
104 PRIVATE Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, U8 tbIdx, U8 fdbk,
105             Bool maxHqRetxReached));
106 void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
107 #ifndef LTE_TDD
108 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
109 RgSchDlHqProcCb      *hqP,
110 RgSchDlSf            *sf,
111 U8                   tbCnt,
112 U8                   *isAck
113 ));
114 #endif
115 #ifdef DL_LA
116 PRIVATE S16 rgSCHDhmUpdateAckNackHistory ARGS((
117         RgSchCellCb             *cell,
118         RgSchUeCb               *ueCb,
119         U8                      hqfdbk,
120         U8                      tbCnt
121         ));
122 #endif
123 #ifdef LTE_TDD
124 PRIVATE Void rgSCHDhmPrcSplBundlFdbk ARGS((
125         RgSchCellCb  *cell,
126         TfuHqInfo    *fdbk,
127         U8            hqCnt
128         ));
129 #ifdef LTE_ADV
130 PRIVATE Void rgSchGetHqFdbkPosForM1 ARGS((
131         RgSchUeCb            *ue,
132         RgSchDlHqProcCb      *hqP,
133         U8                  *isAck, 
134         RgTfuHqInfo          *fdbk,
135         U8                   tbIdx,
136         RgSchTddANInfo       *anInfo
137         ));
138 PRIVATE Void rgSchGetHqFdbkPosForM234 ARGS((
139         RgSchUeCb            *ue,
140         RgSchDlHqProcCb      *hqP,
141         U8                   *isAck, 
142         RgTfuHqInfo          *fdbk,
143         U8                   tbIdx,
144         RgSchTddANInfo       *anInfo,
145         U8                    M,
146         CmLteTimingInfo      timeInfo
147         ));
148 #endif/*LTE_ADV*/
149 #endif/*LTE_TDD*/
150
151 /* Freeing up the HARQ proc blocked for
152  * indefinite time in case of Retx */
153 S16 rgSCHDhmDlRetxAllocFail ARGS((
154 RgSchUeCb        *ue, 
155 RgSchDlHqProcCb  *proc
156 ));
157
158 #ifdef EMTC_ENABLE
159 EXTERN S16 rgSCHDhmEmtcRgrCellCfg ARGS((
160 RgSchCellCb   *cell
161 ));
162 #endif
163
164 #ifdef CA_DBG
165 extern U32 gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
166 extern U32 gSCellSchedCount,gPrimarySchedCount;
167 extern U32 gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
168 extern U32 gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
169 extern U32 gHqFdbkCount;
170
171 #endif
172 #ifdef EMTC_ENABLE
173 EXTERN Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
174 (
175 RgSchEmtcDlSf               *subFrm,
176 RgSchDlHqProcCb            *hqP,
177 U8                         tbIdx,
178 Bool                       isRepeting
179 );
180 EXTERN RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
181 (
182 RgSchCellCb            *cell,
183 CmLteTimingInfo        frm
184 );
185 EXTERN Void rgSCHEmtcHqInfoAlloc ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP));
186 #endif
187 /* forward references */
188
189 /**
190  * @brief This function initializes the DL HARQ Entity of UE.
191  *
192  * @details
193  *
194  *     Function: rgSCHDhmHqEntInit
195  *     Purpose:  This function initializes the DL HARQ entity of 
196  *               UE control block. This is performed at the time
197  *               of creating UE control block.
198  *     
199  *     Invoked by: configuration module
200  *     
201  *  @param[in]  RgSchCellCb*  cell
202  *  @return  RgSchDlHqEnt *
203  *
204  **/
205 /*MS_WORKAROUND for ccpu00122893*/
206 #ifdef ANSI
207 Void rgSCHDhmHqEntReset
208 (
209    RgSchDlHqEnt      *hqE
210 )
211 #else
212 Void rgSCHDhmHqEntReset(hqE)
213    RgSchDlHqEnt      *hqE;
214 #endif
215 {
216    RgSchDlHqProcCb   *hqP;
217    U8                i;
218    cmLListInit(&hqE->inUse);     
219    cmLListInit(&hqE->free);      
220    for (i=0; i < hqE->numHqPrcs; i++)
221    {
222       hqP              = &hqE->procs[i];
223       hqP->hqE         = hqE;
224       hqP->procId      = i;
225       /* Fix  - reset numLch */
226       hqP->tbInfo[0].numLch      = 0;
227       hqP->tbInfo[1].numLch      = 0;
228       hqP->tbInfo[0].txCntr      = 0;
229       hqP->tbInfo[0].ndi         = 0;  /* Initialize the NDI to Zero */
230       hqP->tbInfo[1].txCntr      = 0;
231       hqP->tbInfo[1].ndi         = 0;  /* Initialize the NDI to Zero */
232       hqP->tbInfo[0].tbIdx       = 0;
233       hqP->tbInfo[1].tbIdx       = 1;
234       hqP->tbInfo[0].hqP         = hqP;
235       hqP->tbInfo[1].hqP         = hqP;
236       hqP->tbInfo[0].state       = HQ_TB_ACKED;
237       hqP->tbInfo[1].state       = HQ_TB_ACKED;
238       hqP->tbInfo[0].contResCe   = NOTPRSNT;
239       hqP->tbInfo[1].contResCe   = NOTPRSNT;
240       hqP->lnk.node = (PTR)hqP;
241       //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
242       hqP->hqPLst = NULLP;
243       rgSCHDhmHqPAdd2FreeLst(hqP);
244       hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
245       hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
246       hqP->drxCb.rttIndx  = DRX_INVALID;
247       hqP->drxCb.reTxIndx = DRX_INVALID;
248       hqP->tbInfo[0].cntrRetxAllocFail = 0;
249       hqP->tbInfo[1].cntrRetxAllocFail = 0;
250       hqP->hasDcch = FALSE;
251       hqP->cwSwpEnabled = FALSE;
252       hqP->pdcch   = NULLP;
253       hqP->subFrm  = NULLP;
254
255 #ifdef LTE_ADV
256       rgSCHLaaResetDlHqProcCb(hqP);
257 #endif
258    }
259    RETVOID;
260 } /* rgSCHDhmHqEntReset */
261
262 /**
263  * @brief This function assigns dlHqEnt of raCb to ueCb.
264  *
265  * @details
266  *
267  *     Function: rgSCHDhmAssgnUeHqEntFrmRaCb 
268  *     Purpose:  This function assigns dlHqEnt of raCb to ueCb.
269  *     
270  *     Invoked by: configuration module
271  *     
272  *  @param[in]  RgSchUeCb       *ue
273  *  @param[in]  RgSchRaCb       *raCb
274  *  @return  Void 
275  *
276  **/
277 #ifdef ANSI
278 Void rgSCHDhmAssgnUeHqEntFrmRaCb 
279 (
280 RgSchUeCb       *ue,
281 RgSchRaCb       *raCb
282 )
283 #else
284 Void rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb)
285 RgSchUeCb       *ue;
286 RgSchRaCb       *raCb;
287 #endif
288 {
289
290    ue->cellInfo[0]->hqEnt = raCb->dlHqE;
291    ue->cellInfo[0]->hqEnt->ue = ue;
292    /* Update the DL Harq related information */
293    ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
294    raCb->dlHqE = NULLP;
295    /* Fix : set UE active in DL as UE initialization completed */
296    ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
297    ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
298    rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
299    
300    RETVOID;
301 }
302
303 /**
304  * @brief This function deletes the dlHqEnt.
305  *
306  * @details
307  *
308  *     Function: rgSCHDhmDelHqEnt 
309  *     Purpose:  This function deletes the dlHqEnt.
310  *     
311  *     Invoked by: configuration module
312  *     
313  *  @param[in]  RgSchCellCb       *cell 
314  *  @param[in]  RgSchDlHqEnt      **hqE 
315  *  @return  Void 
316  *
317  **/
318 #ifdef ANSI
319 Void rgSCHDhmDelHqEnt 
320 (
321 RgSchCellCb       *cell,
322 RgSchDlHqEnt      **hqE
323 )
324 #else
325 Void rgSCHDhmDelHqEnt(cell, hqE)
326 RgSchCellCb       *cell;
327 RgSchDlHqEnt      **hqE;
328 #endif
329 {
330
331    if (!(*hqE))
332    {
333       RETVOID;    
334    }
335
336    rgSCHCmnDlDeInitHqEnt(cell, *hqE);
337
338    rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE, 
339        sizeof(RgSchDlHqEnt));
340    
341    RETVOID;
342 }
343
344 #ifdef ANSI
345 RgSchDlHqEnt *rgSCHDhmHqEntInit
346 (
347 RgSchCellCb           *cell
348 )
349 #else
350 RgSchDlHqEnt *rgSCHDhmHqEntInit(cell)
351 RgSchCellCb           *cell;
352 #endif
353 {
354    RgSchDlHqEnt      *hqE;
355    Inst              inst = cell->instIdx;
356
357    /* Init the HARQ data structure */
358    if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
359    {
360       RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
361                                          "rgSCHDhmHqEntInit hqE alloc fail"); 
362       return (NULLP);
363    }
364 #ifdef LTE_TDD
365    /* Init the HARQ processes */
366    hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
367    if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs, 
368                            hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
369    {
370       RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
371                                          "rgSCHDhmHqEntInit hqP alloc fail in hqE"); 
372       return (NULLP);
373    }
374 #else
375    hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
376 #endif
377
378 #ifdef LTE_ADV
379    rgSCHLaaInitDlHqProcCb (cell, hqE);
380 #endif
381
382    /* Initialize maximum tranmission counter */
383    hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
384    
385
386    /* MW_WORKAROUND for ccpu00122893 */
387    rgSCHDhmHqEntReset(hqE); 
388    /* CA Dev Start*/
389    hqE->cell = cell;
390    /* CA Dev End*/
391
392    return (hqE);
393 } /* rgSCHDhmHqEntInit */
394
395 /**
396  * @brief This function gets an available HARQ process.
397  *
398  * @details
399  *
400  *     Function: rgSCHDhmGetAvlHqProc
401  *     Purpose:  This function returns an available HARQ process in 
402  *               the DL direction. All HARQ processes are maintained
403  *               in queues of free and inuse.
404  *
405  *               1. Check if the free queue is empty. If yes, return
406  *                  RFAILED
407  *               2. If not empty, update the proc variable with the
408  *                  first process in the queue. Return ROK.
409  *     
410  *     Invoked by: scheduler
411  *     
412  *  @param[in]  RgSchUeCb           *ue
413  *  @param[in]  CmLteTimingInfo  timingInfo
414  *  @param[out] RgSchDlHqProc       **hqP
415  *  @return  S16       
416  *         -#ROK     if successful
417  *         -#RFAILED otherwise
418  *
419  **/
420 #ifdef ANSI
421 S16 rgSCHDhmGetAvlHqProc
422 (
423 RgSchCellCb           *cell,
424 RgSchUeCb               *ue,
425 CmLteTimingInfo         timingInfo,
426 RgSchDlHqProcCb         **hqP
427 )
428 #else
429 S16 rgSCHDhmGetAvlHqProc (cell, ue, timingInfo, hqP)
430 RgSchCellCb           *cell;
431 RgSchUeCb               *ue;
432 CmLteTimingInfo         timingInfo;
433 RgSchDlHqProcCb         **hqP;
434 #endif
435 {
436    RgSchDlHqEnt         *hqE = NULLP;
437    RgSchDlHqProcCb   *tmpHqProc;
438    CmLList           *tmp;
439
440    hqE      = RG_SCH_CMN_GET_UE_HQE(ue, cell);
441  
442    if (hqE == NULLP)
443    {   
444       RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDhmGetAvlHqProc hqE NULL ue %d"
445                            , ue->ueId);     
446       return RFAILED;
447    }
448
449
450    CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
451
452    if (NULLP == tmp)
453    {
454     RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
455                         "rgSCHDhmGetAvlHqProc free %ld inUse %ld ue %d"
456                                            , hqE->free.count, hqE->inUse.count, ue->ueId);
457       /* No Harq Process available in the free queue. */
458       return RFAILED;
459    }
460
461    tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
462
463 #ifdef LTEMAC_SPS
464    /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
465     * transmissions */
466    if (ue->dl.isSpsHqPInUse)
467    {
468       while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
469       {
470          CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
471          if (!tmp)
472          {
473             break;
474          }
475          tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
476       }
477       if (!tmp)
478       {
479          /* No Harq Process available in the free queue. */
480          return RFAILED;
481       }
482    }
483 #endif
484
485
486    tmpHqProc->tbInfo[0].timingInfo = timingInfo;
487    tmpHqProc->tbInfo[1].timingInfo = timingInfo;
488    tmpHqProc->hasDcch = FALSE;
489    tmpHqProc->cwSwpEnabled = FALSE;
490
491    /* Remove the element from the free Queue */
492    //cmLListDelFrm(&hqE->free, tmp);
493    rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
494
495    /* Add the element into the inUse Queue as well */
496    //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
497    rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
498
499    *hqP = tmpHqProc;
500    
501 #ifdef LTE_ADV
502    rgSCHLaaResetDlHqProcCb(tmpHqProc);
503 #endif
504
505    /* LAA DBG Only */
506    tmpHqProc->tbSizeAtEstimate[0] = 0;
507    tmpHqProc->tbSizeAtEstimate[1] = 0;
508    tmpHqProc->tbSizeAtFnlz[0] = 0;
509    tmpHqProc->tbSizeAtFnlz[1] = 0;
510    tmpHqProc->tbSizeOfMvdTb[0] = 0;
511    tmpHqProc->tbSizeOfMvdTb[1] = 0;
512    tmpHqProc->itbsAtEstimate[0] = 0;
513    tmpHqProc->itbsAtEstimate[1] = 0;
514    tmpHqProc->prbAtEstimate = 0;
515
516    return ROK;
517 } /* rgSCHDhmGetAvlHqProc */
518
519
520 /**
521  * @brief This function adds HARQ process for a given TB in to 
522  *        the inuse queue upon retx.
523  *
524  * @details
525  *
526  *     Function: rgSCHDhmHqTbRetx
527  *     Purpose:  This function handles when a HARQ process is scheduled
528  *               for retransmission. It adds the HARQ procss to inuse
529  *               queue.
530  *               1. Check if this HqP is already added to the inUse
531  *                  queue as part of this function call for other
532  *                  TB's retransmission.
533  *               2. If already present in inUse Q then do not add.
534  *     
535  *     Invoked by: scheduler
536  *     
537  *  @param[in]  RgSchDlHqEnt     *hqE
538  *  @param[in]  CmLteTimingInfo  timingInfo
539  *  @param[out] RgDlHqProc       *hqP
540  *  @param[in]  U8               tbIdx
541  *  @return  Void      
542  *
543  **/
544 #ifdef ANSI
545 Void rgSCHDhmHqTbRetx
546 (
547 RgSchDlHqEnt            *hqE,
548 CmLteTimingInfo         timingInfo,
549 RgSchDlHqProcCb         *hqP,
550 U8                      tbIdx
551 )
552 #else
553 Void rgSCHDhmHqTbRetx(hqE, timingInfo, hqP, tbIdx)
554 RgSchDlHqEnt            *hqE;
555 CmLteTimingInfo         timingInfo;
556 RgSchDlHqProcCb         *hqP;
557 U8                      tbIdx;
558 #endif
559 {
560    U8 othrTbIdx = tbIdx ^ 1;
561
562    hqP->tbInfo[tbIdx].timingInfo = timingInfo;
563
564    if (hqE->msg4Proc == hqP)
565    {
566        RETVOID;
567    }
568    /* fix for ccpu00118633 No Hq proc Avl end*/
569       
570    /* Extra:check if Harq process is already linked to in-use
571       Queue by means of other TB handling. */
572    if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
573    {
574       /*Fix FIXME */
575       if (hqE->msg4Proc != hqP)
576       {
577          //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
578          rgSCHDhmHqPAdd2InUseLst(hqP);
579       }
580    }
581
582     hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
583
584    RETVOID;
585 } /* rgSCHDhmHqTbRetx */
586
587 /**
588  * @brief This function returns last scheduled HARQ process for
589  *        a UE's HARQ entity.
590  *
591  * @details
592  *
593  *     Function: rgSCHDhmLastSchedHqProc
594  *     Purpose:  This function returns the last (most recent)
595  *               process in the inUse list, which corresponds
596  *               to the last scheduled process. Returns NULLP
597  *               if list is empty.
598  *               The reason for introducing this is to have
599  *               an ability to check if UE was scheduled
600  *               in the current subframe (scheduling would
601  *               have caused a proc to be added to the end
602  *               of the list, and checking time (only subframe
603  *               number probably works) would confirm this.
604  *
605  *     Invoked by: scheduler
606  *     
607  *  @param[in]  RgSchDlHqEnt        *hqE
608  *  @return  RgSchDlHqProcCb *
609  *
610  **/
611 #ifdef ANSI
612 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc
613 (
614 RgSchDlHqEnt            *hqE
615 )
616 #else
617 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(hqE)
618 RgSchDlHqEnt            *hqE;
619 #endif
620 {
621    /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
622     * until RACH procedure is completed */
623    if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
624    {
625       return (NULLP);
626    }
627    return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
628 } /* rgSCHDhmLastSchedHqProc */
629
630 #ifdef RGR_V1
631 /**
632  * @brief This function gets an available HARQ process for MSG 4.
633  *
634  * @details
635  *
636  *     Function: rgSCHDhmGetCcchSduHqProc
637  *     Purpose:  This function returns an available HARQ process in 
638  *               the DL direction. All HARQ processes are maintained
639  *               in queues of free and inuse.
640  *
641  *               1. Check if the free queue is empty. If yes, return
642  *                  RFAILED.
643  *               2. If not empty, update the proc variable with the
644  *                  first process in the queue. Return ROK.
645  *     
646  *     Invoked by: scheduler
647  *     
648  *  @param[in]  RgSchRaCb           *raCb
649  *  @param[in]  CmLteTimingInfo  timingInfo
650  *  @param[out] RgSchDlHqProcCb  **hqP
651  *  @return  S16       
652  *         -#ROK     if successful
653  *         -#RFAILED otherwise
654  *
655  **/
656 #ifdef ANSI
657 S16 rgSCHDhmGetCcchSduHqProc
658 (
659 RgSchUeCb               *ueCb,
660 CmLteTimingInfo         timingInfo,
661 RgSchDlHqProcCb         **hqP
662 )
663 #else
664 S16 rgSCHDhmGetCcchSduHqProc (ueCb, timingInfo, hqP)
665 RgSchUeCb               *ueCb;
666 CmLteTimingInfo         timingInfo;
667 RgSchDlHqProcCb         **hqP;
668 #endif
669 {
670    RgSchDlHqProcCb      *tmpHqProc;
671    CmLList              *tmp;
672    RgSchDlHqEnt         *hqE;
673
674    hqE = ueCb->cellInfo[0]->hqEnt;
675    CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
676    if (NULLP == tmp)
677    {
678       /* No Harq Process available in the free queue. */
679       return RFAILED;
680    }
681
682    /* Remove the element from the free Queue and */
683    /* set the MSG 4 HARQ proc pointer            */
684    //cmLListDelFrm(&hqE->free, tmp);
685
686    tmpHqProc             = (RgSchDlHqProcCb *)(tmp->node);
687
688    rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
689
690    tmpHqProc->tbInfo[0].timingInfo = timingInfo;
691    /* Fix : syed minor code reorg */
692    *hqP = tmpHqProc;
693    /*Updating ccchSduProc to identify feedback for CCCH SDU sent without 
694     * Cont Res CE*/
695    hqE->ccchSduProc         = tmpHqProc;
696    //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
697    rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
698    
699    return ROK;
700 } /* rgSCHDhmGetCcchSduHqProc */
701 #endif
702
703 /**
704  * @brief This function gets an available HARQ process for MSG 4.
705  *
706  * @details
707  *
708  *     Function: rgSCHDhmGetMsg4HqProc
709  *     Purpose:  This function returns an available HARQ process in 
710  *               the DL direction. All HARQ processes are maintained
711  *               in queues of free and inuse.
712  *
713  *               1. Check if the free queue is empty. If yes, return
714  *                  RFAILED.
715  *               2. If not empty, update the proc variable with the
716  *                  first process in the queue. Return ROK.
717  *     
718  *     Invoked by: scheduler
719  *     
720  *  @param[in]  RgSchRaCb           *raCb
721  *  @param[in]  CmLteTimingInfo  timingInfo
722  *  @param[out]  RgDlHqProc       **hqP
723  *  @return  S16       
724  *         -#ROK     if successful
725  *         -#RFAILED otherwise
726  *
727  **/
728 #ifdef ANSI
729 S16 rgSCHDhmGetMsg4HqProc
730 (
731 RgSchRaCb               *raCb,
732 CmLteTimingInfo         timingInfo
733 )
734 #else
735 S16 rgSCHDhmGetMsg4HqProc (raCb, timingInfo)
736 RgSchRaCb               *raCb;
737 CmLteTimingInfo         timingInfo;
738 #endif
739 {
740    RgSchDlHqProcCb      *tmpHqProc;
741    CmLList              *tmp;
742    RgSchDlHqEnt         *hqE;
743
744    hqE = raCb->dlHqE;
745    CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
746    if (NULLP == tmp)
747    {
748       /* No Harq Process available in the free queue. */
749       return RFAILED;
750    }
751
752    /* Remove the element from the free Queue and */
753    /* set the MSG 4 HARQ proc pointer            */
754    //cmLListDelFrm(&hqE->free, tmp);
755    tmpHqProc             = (RgSchDlHqProcCb *)(tmp->node);
756    rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
757    tmpHqProc->tbInfo[0].timingInfo = timingInfo;
758    hqE->msg4Proc         = tmpHqProc;
759
760    return ROK;
761 } /* rgSCHDhmGetMsg4HqProc */
762
763 /**
764  * @brief This function releases a HARQ process.
765  *
766  * @details
767  *
768  *     Function: rgSCHDhmRlsHqpTb 
769  *     Purpose:  This function resets the TB specific fields
770  *               Based on the other TBs state, this HqProcess
771  *               is returned to the HqEnt.
772  *     
773  *               1. Add the HARQ process to the free queue.
774  *     Invoked by: scheduler and HARQ processing
775  *     
776  *  @param[in]  RgDlHqProc    *hqP
777  *  @param[in]  U8            tbIdx
778  *  @param[in]  Bool          togNdi 
779  *  @return  Void      
780  *
781  **/
782 #ifdef ANSI
783 Void rgSCHDhmRlsHqpTb
784 (
785 RgSchDlHqProcCb         *hqP,
786 U8                      tbIdx,
787 Bool                    togNdi
788
789 #else
790 Void rgSCHDhmRlsHqpTb(hqP, tbIdx, togNdi) 
791 RgSchDlHqProcCb         *hqP;
792 U8                      tbIdx;
793 Bool                    togNdi;
794 #endif
795 {
796    RgSchDlHqEnt         *hqE;
797    U8                   othrTbIdx = tbIdx ^ 1;
798 #ifdef LTEMAC_SPS
799    RgSchCmnDlHqProc        *cmnHqDl;
800 #endif
801    /* L2_COUNTERS */
802 #ifdef LTE_L2_MEAS
803    RgSchDlLcCb*         lcCb = NULLP;
804    U8                   numLch = 0;
805 #endif
806
807    /* Reset all tbInfo values */
808
809    hqE = hqP->hqE;
810
811 #ifdef MAC_SCH_STATS
812    if (hqP->hqE->ue != NULLP)
813    {
814       RgSchUeCb      *ueCb  = hqP->hqE->ue;
815       RgSchCmnUe     *cmnUe = (RgSchCmnUe*)ueCb->sch;
816       RgSchCmnDlUe   *dlUe  = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
817       U8             cqi    = dlUe->mimoInfo.cwInfo[0].cqi;
818       /* to get retransmission, decreasing transmission counter */
819       U16            numDlRetx = hqP->tbInfo[0].txCntr-1; 
820       U8             tbs       = dlUe->mimoInfo.cwInfo[0].iTbs[0];
821       static U32 retxCnt1      = 0;
822
823       RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
824             hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
825
826       switch (numDlRetx)
827       {
828          case 1:
829             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
830             break;
831          case 2:
832             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
833             break;
834          case 3:
835             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
836             break;
837          case 4:
838             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
839             break;
840       }
841       hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
842              hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
843             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
844             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
845             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4); 
846
847       retxCnt1 += numDlRetx;
848    }
849 #endif /* MAC_SCH_STATS */
850    RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
851    /* Toggle ndi */
852    if(togNdi == TRUE)
853    {
854       hqP->tbInfo[tbIdx].ndi          ^= 1;
855    }
856
857    /* L2_COUNTERS */
858 #ifdef LTE_L2_MEAS
859    for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
860    {
861       if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
862                   hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
863       {
864          if (lcCb->lcType == CM_LTE_LCH_DTCH)
865          {
866             if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
867             {
868                hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
869             }
870
871             if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
872             {
873                lcCb->qciCb->dlUeCount--;
874             }
875          }
876       }
877    }
878 #endif
879
880    /* Initialization */
881    hqP->tbInfo[tbIdx].tbSz           = 0;
882    hqP->tbInfo[tbIdx].numLch         = 0;
883    hqP->tbInfo[tbIdx].txCntr         = 0;
884    /* FOR ACK NACK REP */
885    hqP->tbInfo[tbIdx].fbkRepCntr     = 0;
886    hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
887    hqP->tbInfo[tbIdx].ackCount       = 0;
888    /* pdcch is moved from TbCb to HqCb.
889       This pdcch will be set to NULL when 
890       HqCb will be pushed to free list*/
891    hqP->tbInfo[tbIdx].state          = HQ_TB_ACKED;
892    hqP->tbInfo[tbIdx].isAckNackDtx   = 0;
893    hqP->tbInfo[tbIdx].nackCount      = 0;
894    hqP->tbInfo[tbIdx].dtxCount       = 0;
895    hqP->tbInfo[tbIdx].schdTa.pres    = NOTPRSNT;
896    hqP->tbInfo[tbIdx].contResCe      = NOTPRSNT;
897 #ifdef LTE_ADV
898    hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
899 #endif
900    hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
901    /* Handling msg4 hqProc */
902    if (hqE->msg4Proc == hqP)
903    {
904       hqE->msg4Proc = NULLP;
905       hqP->pdcch    = NULLP;
906       hqP->subFrm   = NULLP;
907       /* Add the proc to the free list */
908       //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
909       rgSCHDhmHqPAdd2FreeLst(hqP);
910       RETVOID;
911    }
912 #ifdef RGR_V1
913    /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
914     * is dangerous and it expects ccchSduProc is the first
915     * DL allocation for a UE, and considering a scenario
916     * of multiple UEs contending and 1 UE per TTI, this 
917     * assumption can be wronged, leading to inUse list
918     * corruption. Hence altering this check.
919     * A better approach would be do avoid having this 
920     * special handling for ccchSduProc, streamline 
921     * it with the usual approach. */
922    if (hqE->ccchSduProc == hqP)
923    {
924       hqE->ccchSduProc = NULLP;
925       /* ccpu00137582- If hqP is in reTxLst then it will be no more available
926        * in inUse list, Hence need not to delete from inUse list*/
927       if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
928       {
929          //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
930          rgSCHDhmHqPDelFrmInUseLst(hqP);
931       }
932       else
933       {
934          hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
935       }
936       hqP->pdcch    = NULLP;
937       hqP->subFrm   = NULLP;
938       /* Add the proc to the free list */
939       //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
940       rgSCHDhmHqPAdd2FreeLst(hqP);
941       RETVOID;
942    }
943 #endif
944       
945    /* extra:check if other TB is also free for allocation then 
946     * add it to FREE List */
947    switch(hqP->tbInfo[othrTbIdx].state)
948    {
949       case HQ_TB_ACKED:
950          /* Remove the element from the inUse Queue */
951          /* Freeing up the HARQ proc blocked for
952           * indefinite time in case of Retx */
953          if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
954          {
955             //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
956             rgSCHDhmHqPDelFrmInUseLst(hqP);
957          }
958          hqP->pdcch   = NULLP;
959          hqP->subFrm  = NULLP;
960 #ifdef EMTC_ENABLE
961 rgEmtcsetNullSubFrm(hqP);
962 #endif
963          /* Add the proc to the free list */
964          //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
965          rgSCHDhmHqPAdd2FreeLst(hqP);
966 #ifdef LAA_DBG
967          if (hqE->free.count > 8)
968          {
969             int *p = NULL;
970             printf("Crashing invalid hq count after free \n");
971             printf("Crashing %d \n", *p);
972             *p = 10;
973          }
974 #endif
975 #ifdef LTEMAC_SPS
976          cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
977          if (cmnHqDl) 
978          {
979             cmnHqDl->spsAction = 0;
980             cmnHqDl->isSpsActv = FALSE;
981             cmnHqDl->isSpsSvcSchd = FALSE;
982          }
983 #endif
984          break;
985          case HQ_TB_NACKED:
986          /* Remove the element from the inUse Queue */
987          /* Freeing up the HARQ proc blocked for
988           * indefinite time in case of Retx */
989          if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
990          {
991             //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
992             rgSCHDhmHqPDelFrmInUseLst(hqP);
993          }
994          break;
995          case HQ_TB_WAITING:
996             /* Do nothing */
997          break;
998    }
999    
1000    hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
1001
1002    RETVOID;
1003 } /* rgSCHDhmRlsHqpTb */
1004
1005 /**
1006  * @brief This function releases a HARQ process.
1007  *
1008  * @details
1009  *
1010  *     Function: rgSCHDhmRlsHqProc
1011  *     Purpose:  This function returns a HARQ process to HARQ Entity 
1012  *               in the DL direction.
1013  *     
1014  *               1. Add the HARQ process to the free queue.
1015  *     Invoked by: scheduler and HARQ processing
1016  *     
1017  *  @param[in]  RgDlHqProc    *hqP
1018  *  @return  Void      
1019  *
1020  **/
1021 #ifdef ANSI
1022 Void rgSCHDhmRlsHqProc
1023 (
1024 RgSchDlHqProcCb         *hqP
1025 )
1026 #else
1027 Void rgSCHDhmRlsHqProc(hqP)
1028 RgSchDlHqProcCb         *hqP;
1029 #endif
1030 {
1031
1032
1033 #ifdef MAC_SCH_STATS
1034     /* THIS FUNCTION IS NOT CALLED */
1035    if (hqP->hqE->ue != NULLP)
1036    {
1037       RgSchUeCb      *ueCb  = hqP->hqE->ue;
1038       RgSchCmnUe     *cmnUe = (RgSchCmnUe*)ueCb->sch;
1039       RgSchCmnDlUe   *dlUe  = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1040       U8             cqi    = dlUe->mimoInfo.cwInfo[0].cqi;
1041       /* to get retransmission, decreasing transmission counter */
1042       U16            numDlRetx = hqP->tbInfo[0].txCntr-1; 
1043       U8             tbs       = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1044
1045       RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
1046
1047       switch (numDlRetx)
1048       {
1049          case 1:
1050             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
1051             break;
1052          case 2:
1053             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
1054             break;
1055          case 3:
1056             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
1057             break;
1058          case 4:
1059             hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
1060             break;
1061       }
1062       hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
1063              hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
1064             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
1065             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
1066             (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
1067    }
1068 #endif /* MAC_SCH_STATS */
1069       hqP->pdcch   = NULLP;
1070       hqP->subFrm  = NULLP;
1071 #ifdef EMTC_ENABLE
1072 rgEmtcsetNullSubFrm(hqP);
1073 #endif
1074       rgSCHDhmHqPDelFrmInUseLst(hqP);
1075       rgSCHDhmHqPAdd2FreeLst(hqP);
1076 #ifdef TFU_UPGRADE
1077    hqP->tbCnt = 0;
1078 #endif
1079
1080    RETVOID;
1081 } /* rgSCHDhmRlsHqProc */
1082
1083 #ifdef LTEMAC_SPS
1084 /**
1085  * @brief This function gets HARQ process with the given ID.
1086  *
1087  * @details
1088  *
1089  *     Function: rgSCHDhmGetHqProcFrmId
1090  *     Purpose:  This function returns the HARQ process with the given ID.
1091  *     Invoked by: ROM
1092  *     
1093  *  @param[in]  RgSchUeCb     *ue
1094  *  @param[in]  U8            idx
1095  *  @param[in]  RgDlHqProc    **hqP
1096  *  @return  S16       
1097  *         -#   ROK     if successful
1098  *         -#   RFAILED otherwise
1099  *
1100  **/
1101 #ifdef ANSI
1102 S16 rgSCHDhmGetHqProcFrmId
1103 (
1104 RgSchCellCb           *cell,
1105 RgSchUeCb               *ue,
1106 U8                      idx,
1107 RgSchDlHqProcCb         **hqP
1108 )
1109 #else
1110 S16 rgSCHDhmGetHqProcFrmId(cell, ue, idx, hqP)
1111 RgSchCellCb           *cell;
1112 RgSchUeCb               *ue;
1113 U8                      idx;
1114 RgSchDlHqProcCb         **hqP;
1115 #endif
1116 {
1117    RgSchDlHqEnt         *hqE;
1118
1119    hqE      = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1120    /* Pick the proc based on the index provided */
1121    *hqP = &(hqE->procs[idx]);
1122
1123    return ROK;
1124 } /* rgSCHDhmGetHqProcFrmId */
1125
1126 /**
1127  * @brief This function gets SPS HARQ process from the given time
1128  *
1129  * @details
1130  *
1131  *     Function: rgSCHDhmSpsDlGetHqProc
1132  *     Purpose:  This function returns the SPS HARQ process for the given time
1133  *     
1134  *  @param[in]  RgSchUeCb       *ue
1135  *  @param[in]  CmLteTimingInfo timingInfo
1136  *  @return  RgSchDlHqProcCb control block 
1137  *
1138  **/
1139 #ifdef ANSI
1140 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc
1141 (
1142 RgSchCellCb           *cell,
1143 RgSchUeCb               *ue,
1144 CmLteTimingInfo         timingInfo
1145 )
1146 #else
1147 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(cell, ue, timingInfo)
1148 RgSchCellCb           *cell,
1149 RgSchUeCb               *ue;
1150 CmLteTimingInfo         timingInfo;
1151 #endif
1152 {
1153    RgSchDlHqEnt         *hqE;
1154    U8                    idx;
1155    RgSchDlHqProcCb       *hqProc = NULLP;
1156    CmLList               *tmp = NULLP;
1157
1158    hqE      = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1159
1160    CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1161
1162    if (NULLP == tmp)
1163    {
1164       /* No Harq Process available in the free queue. */
1165       return (NULLP);
1166    }
1167
1168    idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1169          ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1170
1171
1172    hqProc = (RgSchDlHqProcCb *)(tmp->node);
1173
1174    /* If the  HARQ process is in the free list, retrieve the process */
1175    while (hqProc->procId != idx)
1176    {
1177       CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1178       if (!tmp)
1179       {
1180          break;
1181       }
1182       hqProc = (RgSchDlHqProcCb *)(tmp->node);
1183    }
1184
1185    if (!tmp)
1186    {
1187       /* No Harq Process available in the free queue. */
1188       return (NULLP);
1189    }
1190
1191    hqProc->tbInfo[0].timingInfo = timingInfo;
1192    hqProc->tbInfo[1].timingInfo = timingInfo;
1193
1194    /* Remove the element from the free Queue */
1195    //cmLListDelFrm(&hqE->free, tmp);
1196    rgSCHDhmHqPDelFrmFreeLst(hqProc);
1197
1198    /* Add the element into the inUse Queue as well */
1199    //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1200    rgSCHDhmHqPAdd2InUseLst(hqProc);
1201
1202 #ifdef LTE_ADV
1203    rgSCHLaaResetDlHqProcCb(hqProc);
1204 #endif
1205
1206    return (hqProc);
1207 } /* rgSCHDhmSpsDlGetHqProc */
1208 #endif /* LTEMAC_SPS */
1209
1210
1211 /** * @brief Handler for handling TA. 
1212  *
1213  * @details
1214  *
1215  *     Function : rgSCHDhmFdbkIndHndlTa
1216  *     
1217  *     This function handles the TA state and values based on the 
1218  *     feedback indication received.
1219  *           
1220  *  @param[in]  RgSchDlHqProcCb   *hqP
1221  *  @param[in]  U8                tbIdx
1222  *  @param[in]  U8                fdbk
1223  *  @return     Void
1224  *      -# None.
1225  **/
1226 #ifdef ANSI
1227 PRIVATE Void rgSCHDhmFdbkIndHndlTa
1228 (
1229 RgSchDlHqProcCb   *hqP,
1230 U8                tbIdx,
1231 U8                fdbk,
1232 Bool              maxHqRetxReached
1233 )
1234 #else
1235 PRIVATE Void rgSCHDhmFdbkIndHndlTa(hqP, tbIdx, fdbk,maxHqRetxReached)
1236 RgSchDlHqProcCb   *hqP;
1237 U8                tbIdx;
1238 U8                fdbk;
1239 Bool              maxHqRetxReached;
1240 #endif
1241 {
1242    RgSchUeCb      *ueCb;
1243    RgSchCellCb    *cell;
1244
1245    ueCb  = hqP->hqE->ue;
1246    cell  = ueCb->cell;
1247    switch(fdbk)
1248    {
1249       case TRUE:
1250          /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/  
1251          hqP->tbInfo[tbIdx].taSnt =  FALSE;
1252          /* To prevent duplicate inserts of ueCb into TA list */
1253          if (ueCb->taLnk.node == NULLP)
1254          {
1255             ueCb->taLnk.node         =  (PTR)ueCb;
1256             cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1257          }
1258          else
1259          { 
1260 #ifdef DEBUGP            
1261             RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Trying to add CRNTI:%d into TA"
1262                      "ACK List twice", ueCb->ueId);
1263 #endif            
1264          } 
1265          break;
1266
1267       case FALSE:
1268          /* If Ta was sent and its the final NACK, then reset only the 
1269           * taState to IDLE and not the value */
1270          /* Changed handling in case maxhqretx is reached for TA */
1271          if(TRUE == maxHqRetxReached)
1272          {
1273             hqP->tbInfo[tbIdx].taSnt    =  FALSE;
1274             hqP->hqE->ue->dl.taCb.state =  RGSCH_TA_IDLE;
1275
1276             rgSCHUtlReTxTa(cell, ueCb);
1277             RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId, 
1278                   "Nack Rcvd for TA. Max Tries Attempted");
1279          }
1280          break;
1281       case TFU_HQFDB_DTX:
1282          /* If Ta was sent and its the final NACK, then reset only the 
1283           * taState to IDLE and not the value */
1284          if(TRUE == maxHqRetxReached)
1285          {
1286             hqP->tbInfo[tbIdx].taSnt    =  FALSE;
1287             hqP->hqE->ue->dl.taCb.state =  RGSCH_TA_IDLE;
1288
1289             /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1290              * issue for VoLTE call */
1291             rgSCHUtlDlTARpt(cell, ueCb);
1292          }
1293          break;
1294
1295       default:
1296          break;
1297    }
1298
1299    RETVOID;
1300 } /* rgSCHDhmFdbkIndHndlTa */
1301
1302 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1303 /** * @brief Handler for scheduling TA.
1304  *
1305  * @details
1306  *
1307  *     Function : rgSCHDhmShcdTa
1308  *     
1309  *     This function is called by scheduler when resource allocation
1310  *     for TA transmission is done.
1311  *           
1312  *  @param[in]  RgSchUeCb         *ue
1313  *  @param[out] RgSchDlHqTbCb     *tbInfo
1314  *  @return     Void
1315  *      -# None.
1316  **/
1317 #ifdef ANSI
1318 Void rgSCHDhmSchdTa
1319 (
1320 RgSchUeCb         *ueCb,
1321 RgSchDlHqTbCb     *tbInfo
1322 )
1323 #else
1324 Void rgSCHDhmSchdTa(ueCb, tbInfo)
1325 RgSchUeCb         *ueCb;
1326 RgSchDlHqTbCb     *tbInfo;
1327 #endif
1328 {
1329
1330    ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1331     ueCb->dl.taCb.numRemSf  =  2; 
1332    tbInfo->schdTa.pres    = PRSNT_NODEF;
1333    tbInfo->schdTa.val     = ueCb->dl.taCb.ta;
1334
1335    RETVOID;
1336 } /* rgSCHDhmSchdTa */
1337
1338 #ifdef LTE_TDD
1339 /** * @brief Handler for fetching Harq Proc given the feeback information.
1340  *
1341  * @details
1342  *
1343  *     Function : rgSCHDhmHqProcByFdbkTime
1344  *
1345  *     This function shall fetch all the harq proc having the feedback
1346  *     timing information.
1347  *
1348  *  @param[in]  RgSchDlHqEnt       *hqE
1349  *  @param[in]  CmLteTimingInfo    timeInfo
1350  *  @param[in]  Bool               *isMsg4
1351  *  @param[out] RgSchDlHqProcCb    **hqPrcs
1352  *  @param[out] U8                 *numTbs
1353  *  @param[out] S8                 *tbStrtIdx
1354  *  @param[out] U8                 *cntHqPrcs
1355  *  @return     S16
1356  **/
1357 #ifdef ANSI
1358 PRIVATE S16 rgSCHDhmHqProcByFdbkTime
1359 (
1360 RgSchDlHqEnt            *hqE,
1361 CmLteTimingInfo         timeInfo,
1362 Bool                    *isMsg4,
1363 RgSchDlHqProcCb         **hqPrcs,
1364 U8                      *numTbs,
1365 S8                      *tbStrtIdx,
1366 U8                      *cntHqPrcs,
1367 RgSchCellCb             *cell
1368 )
1369 #else
1370 PRIVATE S16 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, isMsg4, hqPrcs,
1371                                      numTbs, tbStrtIdx, cntHqPrcs)
1372 RgSchDlHqEnt            *hqE;
1373 CmLteTimingInfo         timeInfo;
1374 Bool                    *isMsg4;
1375 RgSchDlHqProcCb         **hqPrcs;
1376 U8                      *numTbs;
1377 S8                      *tbStrtIdx;
1378 U8                      *cntHqPrcs;
1379 RgSchCellCb             *cell;
1380 #endif
1381 {
1382    RgSchDlHqTbCb        *tbCb;
1383    RgSchDlHqProcCb      *hqP;
1384    CmLteTimingInfo      schdSfTime;
1385    RgSchTddDlAscSetIdxK ascIdx;
1386    U8                   noFdbks;
1387    U8                   i;
1388    U8                   idx;
1389    U8                   dlIdx;
1390    CmLListCp            *lnk;
1391    CmLList              *node;
1392
1393    *cntHqPrcs = 0;
1394    if (hqE->msg4Proc)
1395    {
1396       if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1397       {
1398           *isMsg4 = TRUE;
1399           hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1400           tbStrtIdx[*cntHqPrcs] = 0;
1401           numTbs[*cntHqPrcs] = 1;
1402           (*cntHqPrcs)++;
1403           return ROK;
1404       }
1405    }
1406    ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1407    noFdbks = ascIdx.numFdbkSubfrms;
1408
1409    for(idx=0; idx<noFdbks; idx++)
1410    {
1411       /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output 
1412        * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is 
1413        * serving the purpose */
1414       RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1415       dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1416       lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1417       node = lnk->first;
1418       while (node)
1419       {
1420          hqP = (RgSchDlHqProcCb*)node->node;
1421          node = node->next; 
1422
1423          numTbs[*cntHqPrcs] = 0;
1424          tbStrtIdx[*cntHqPrcs] = -1;
1425          for (i = 0; i < 2; i++)
1426          {
1427             /* Extra:check which TB is waiting for feedback */
1428             if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1429             {
1430                if (tbStrtIdx[*cntHqPrcs] == -1)
1431                {
1432                   tbStrtIdx[*cntHqPrcs] = i;
1433                }
1434                numTbs[*cntHqPrcs]++;
1435             }
1436          }
1437          if (numTbs[*cntHqPrcs] > 0)
1438          {
1439             hqPrcs[*cntHqPrcs] = hqP;
1440             (*cntHqPrcs)++;
1441          }
1442       }
1443
1444       /* AN REP Hq Procs */
1445       node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1446       while(node)
1447       {
1448          tbCb = (RgSchDlHqTbCb *)(node->node);
1449          hqP = tbCb->hqP;
1450
1451          numTbs[*cntHqPrcs] = 0;
1452          tbStrtIdx[*cntHqPrcs] = -1;
1453          for (i = 0; i < 2; i++)
1454          {
1455             /* Extra:check which TB is waiting for feedback */
1456             if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1457             {
1458                if (tbStrtIdx[*cntHqPrcs] == -1)
1459                {
1460                   tbStrtIdx[*cntHqPrcs] = i;
1461                }
1462                numTbs[*cntHqPrcs]++;
1463             }
1464          }
1465          if (numTbs[*cntHqPrcs] == 2)
1466          {
1467             node = node->next;
1468          }
1469          if (numTbs[*cntHqPrcs] > 0)
1470          {
1471             hqPrcs[*cntHqPrcs] = hqP;
1472             (*cntHqPrcs)++;
1473          }
1474
1475          node = node->next;
1476       }
1477    }
1478
1479
1480    return ROK;
1481 }
1482 #else  /* LTE_TDD */
1483 /** * @brief Handler for fetching Harq Proc given the timming information.
1484  *
1485  * @details
1486  *
1487  *     Function : rgSCHDhmHqProcByTime
1488  *     
1489  *     This function shall fetch the harq proc using the timing information.
1490  *           
1491  *  @param[in]  RgSchDlHqEnt    *hqE
1492  *  @param[in]  CmLteTimingInfo timeInfo
1493  *  @param[in]  Bool            *isMsg4
1494  *  @param[out] U8              *numTbs
1495  *  @param[out] S8              *tbStrtIdx 
1496  *  @return     RgSchDlHqProcCb*
1497  *      -# RgSchDlHqProcCb* 
1498  *      -# NULLP 
1499  **/
1500 #ifdef ANSI
1501 RgSchDlHqProcCb *rgSCHDhmHqProcByTime
1502 (
1503 RgSchDlHqEnt            *hqE,
1504 CmLteTimingInfo         timeInfo,
1505 Bool                    *isMsg4,
1506 RgSchDlSf               *sf
1507 )
1508 #else
1509 RgSchDlHqProcCb *rgSCHDhmHqProcByTime(hqE, timeInfo,
1510                                               isMsg4,sf)
1511 RgSchDlHqEnt            *hqE;
1512 CmLteTimingInfo         timeInfo;
1513 Bool                    *isMsg4;
1514 RgSchDlSf               *sf;
1515 #endif
1516 {
1517    if (hqE->msg4Proc)
1518    {
1519       if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1520       {
1521           *isMsg4    = TRUE;
1522           return (hqE->msg4Proc);
1523       }
1524    }
1525    
1526    return (NULLP);
1527 }
1528 #endif
1529
1530 /** * @brief Handler for handling the harq transaction failure.
1531  *
1532  * @details
1533  *
1534  *     Function : rgSCHDhmHqTbTrnsFail
1535  *     
1536  *     This function handled the harq TB transaction failure :
1537  *     - If retries have not reached maximum, add to the reTx Q.
1538  *     - else do error recovery.
1539  *           
1540  *  @param[in]  RgSchCellCb             *cell
1541  *  @param[in]  RgSchDlHqProcCb         *hqP
1542  *  @param[in]  U8                      tbCnt
1543  *  @param[out] Bool                    *isMaxRetx
1544  *  @return    Void
1545  *             -#None.
1546  *      
1547  **/
1548 #ifdef ANSI
1549 Void rgSCHDhmHqTbTrnsFail
1550 (
1551 RgSchCellCb             *cell,
1552 RgSchDlHqProcCb         *hqP,
1553 U8                      tbCnt,
1554 Bool                    *isMaxRetx
1555 )
1556 #else
1557 Void rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, isMaxRetx)
1558 RgSchCellCb             *cell;
1559 RgSchDlHqProcCb         *hqP;
1560 U8                      tbCnt;
1561 Bool                    *isMaxRetx;
1562 #endif
1563 {
1564    RgSchDlHqEnt         *hqE;
1565    U8                   maxHqTx;
1566
1567    hqE = hqP->hqE;
1568
1569    /* Fetch the maximum number of harq transmissions */
1570    if (hqE->msg4Proc == hqP)
1571    {
1572 #ifdef RGR_V1
1573       if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1574       {
1575          RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1576                "rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1577                hqP->hqE->raCb->tmpCrnti);
1578          rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1579          RETVOID;
1580       }
1581 #endif
1582       maxHqTx  = cell->dlHqCfg.maxMsg4HqTx;
1583    }
1584    else
1585    {
1586       maxHqTx  = hqE->maxHqTx;
1587    }
1588
1589 #ifdef MAC_SCH_STATS
1590    if (hqE->ue != NULLP)
1591    {
1592       RgSchUeCb      *ueCb  = hqE->ue;
1593       RgSchCmnUe     *cmnUe = (RgSchCmnUe*)ueCb->sch;
1594       RgSchCmnDlUe   *dlUe  = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1595       U8             tbs    = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1596       static U32 retxCnt    = 0;
1597
1598       {
1599          ++retxCnt;
1600          hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1601       }
1602       RG_SCH_CMN_DL_TBS_TO_MCS(tbs, 
1603                (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1604    }
1605 #endif /* MAC_SCH_STATS */ 
1606
1607    RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1608    /* Reset the PDCCH reference */
1609    hqP->pdcch =  NULL;
1610    if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1611    {
1612       hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1613
1614       if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1615       {
1616
1617          /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1618           * for the UE. Addtion to the retransmission queue will be done on
1619           * HARQ RTT timer expiry.--*/
1620          switch(hqP->tbInfo[tbCnt ^ 1].state)
1621          {
1622             case HQ_TB_ACKED:
1623                /*As the first TB is ACKED we have not started HARQ RTT for the
1624                 * HqP, so start it here.*/
1625                //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1626                rgSCHDhmHqPDelFrmInUseLst(hqP);
1627                /* CA Dev Start */
1628                rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1629                /* CA Dev End*/
1630 #ifdef LTEMAC_SPS
1631                /* Integration fix */   
1632                /* Setting cntrRetxAllocFail to MAX value here */
1633                /* Since the hqP entry is already deleted from inUse list of HqEntity
1634                   setting the value here will ensure the entry is not deleted
1635                   again during release harq proc */
1636                if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) && 
1637                      (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1638                {
1639                   hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1640                   if (hqP->tbInfo[1].txCntr)
1641                   {
1642                      hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1643                   }
1644                }
1645 #endif
1646                break;
1647             case HQ_TB_NACKED:
1648                /*As the first TB is NACKED we have already started HARQ RTT for the
1649                 * HqP, so dont start it here, just delete from in use queue.*/
1650                //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1651                rgSCHDhmHqPDelFrmInUseLst(hqP);
1652                break;
1653             case HQ_TB_WAITING:
1654                /*As this is the first TB to be fed back and is NACKED start
1655                 * the HARQ RTT here.*/
1656                /* CA Dev Start */
1657                rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1658                /* CA Dev End*/
1659                break;
1660          }
1661          RETVOID;
1662       }
1663       /* extra:check if already removed as part of other TB processing
1664        * then donot remove from InUse Q */
1665       /* Check if other TB is not waiting for feedback.
1666        * Makinf sure hqP is present in inUse Queue until
1667        * it is fedback for all its TBs */
1668       switch(hqP->tbInfo[tbCnt ^ 1].state)
1669       {
1670          case HQ_TB_ACKED:
1671             /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1672             if(hqE->msg4Proc != hqP)
1673             {
1674               //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1675               rgSCHDhmHqPDelFrmInUseLst(hqP);
1676             }
1677             /* Retransmission needs to be done. Add to the scheduler Q */
1678             rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1679             break;
1680          case HQ_TB_NACKED:
1681             /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1682             if(hqE->msg4Proc != hqP)
1683             {
1684               //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1685               rgSCHDhmHqPDelFrmInUseLst(hqP);
1686             }
1687             break;
1688          case HQ_TB_WAITING:
1689             /* Retransmission needs to be done. Add to the scheduler Q */
1690             /* CA Dev Start*/
1691             rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1692             /* CA Dev End*/
1693             break;
1694       }
1695       *isMaxRetx = FALSE; 
1696    }
1697    else
1698    {
1699       /* Failure Notification */
1700       if (hqE->msg4Proc == hqP)
1701       {
1702        /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1703          rgNumMsg4FailMaxRetx++;
1704 #ifdef TENB_STATS
1705          hqE->cell->tenbStats->sch.msg4Fail ++;
1706 #endif
1707
1708          /* Perform RAM MSG4 done processing */
1709          RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1710                "rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1711                hqP->hqE->raCb->tmpCrnti);
1712          rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1713       }
1714       else
1715       {
1716          /* Release the Harq Proc */
1717          rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1718       }
1719       *isMaxRetx = TRUE; 
1720    }
1721
1722    RETVOID;
1723 } /* rgSCHDhmHqTbTrnsFail */
1724
1725 U32 rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, 
1726                                    {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1727 #ifdef LTE_TDD
1728 #ifdef LTE_ADV
1729 /** * @brief Function to decode the position of HarqFb for M=1.
1730  *
1731  * @details
1732  *
1733  *     Function : rgSchGetHqFdbkPosForM1
1734  *           
1735  *  @param[in]  RgSchUeCb            *ue,
1736  *  @param[in]  RgSchDlHqProcCb      *hqP,
1737  *  @param[in]  U8                 *isAck, 
1738  *  @param[in]  RgTfuHqInfo          *fdbk,
1739  *  @param[in]  U8                   tbIdx,
1740  *  @param[in]  RgSchTddANInfo       *anInfo;
1741  *  @return     RETVOID
1742  **/
1743 #ifdef ANSI
1744 PRIVATE Void rgSchGetHqFdbkPosForM1
1745 (
1746  RgSchUeCb            *ue,
1747  RgSchDlHqProcCb      *hqP,
1748  U8                  *isAck, 
1749  RgTfuHqInfo          *fdbk,
1750  U8                   tbIdx,
1751  RgSchTddANInfo       *anInfo
1752  )
1753 #else
1754 PRIVATE Void rgSchGetHqFdbkPosForM1(ue,hqP,isAck,fdbk,tbIdx,anInfo)
1755  RgSchUeCb            *ue;
1756  RgSchDlHqProcCb      *hqP;
1757  U8                   *isAck;
1758  RgTfuHqInfo          *fdbk;
1759  U8                   tbIdx;
1760  RgSchTddANInfo       *anInfo;
1761 #endif
1762 {
1763    if((ue != NULLP))
1764    {
1765       /* handle pusch and pucch cases */
1766       /* PUSCH:: Fdbks are in the increasing order
1767        * of servCellIdx as per 36.212 section 5.2.26*/
1768       switch(ue->f1bCsAVal)
1769       {
1770          case RG_SCH_A_VAL_2:
1771             {
1772                if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
1773                {
1774                   *isAck = fdbk->isAck[1];/*SCell*/
1775                }
1776                else
1777                {
1778                   *isAck = fdbk->isAck[0];/*PCell*/
1779                }
1780                break;
1781             }
1782          case RG_SCH_A_VAL_3:
1783             {
1784                   if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
1785                   {
1786                      U8 cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1787                            hqP->hqE->cell->cellId,
1788                            hqP->hqE->ue);
1789
1790                      if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1791                      {/*SCell - mimo mode*/
1792                         if(TRUE == fdbk->isPusch)
1793                         {
1794                            *isAck = fdbk->isAck[tbIdx + 1];
1795                         }
1796                         else
1797                         {
1798                            *isAck = fdbk->isAck[tbIdx];
1799                         }
1800                      }
1801                      else
1802                      {/*SCell - siso mode*/
1803                         *isAck = fdbk->isAck[2];
1804                      }
1805                   }else
1806                   {
1807                      if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1808                      {/*Primary Cell - mimo mode*/
1809                         *isAck = fdbk->isAck[tbIdx];
1810                      }
1811                      else
1812                      {/*Primary Cell - siso mode*/
1813                         if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1814                         {
1815                            /* If fdbk is on PUSCH but its not an SPS occasion*/
1816                            *isAck = fdbk->isAck[0];
1817                         }
1818                         else
1819                         {
1820                            /* If fdbk is on PUCCH or its an SPS occasion*/
1821                            *isAck = fdbk->isAck[2];
1822                         }
1823                      }
1824                   }
1825                break;
1826             }
1827          case RG_SCH_A_VAL_4:
1828             {
1829                if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
1830                {
1831                   *isAck = fdbk->isAck[tbIdx + 2];
1832                }
1833                else
1834                {
1835                   *isAck = fdbk->isAck[tbIdx];
1836                }
1837                break;
1838             }
1839          default:
1840             break;
1841       }
1842    }
1843    RETVOID;
1844 }/* End of rgSchGetHqFdbkPosForM1 */
1845
1846 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1847  *
1848  * @details
1849  *
1850  *     Function : rgSchGetHqFdbkPosForM234
1851  *           
1852  *  @param[in]  RgSchUeCb            *ue,
1853  *  @param[in]  RgSchDlHqProcCb      *hqP,
1854  *  @param[in]  U8                   *isAck, 
1855  *  @param[in]  RgTfuHqInfo          *fdbk,
1856  *  @param[in]  U8                   tbIdx,
1857  *  @param[in]  RgSchTddANInfo       *anInfo;
1858  *  @param[in]  CmLteTimingInfo      timeInfo;
1859  *  @return     RETVOID
1860  **/
1861 #ifdef ANSI
1862 PRIVATE Void rgSchGetHqFdbkPosForM234
1863 (
1864  RgSchUeCb            *ue,
1865  RgSchDlHqProcCb      *hqP,
1866  U8                   *isAck, 
1867  RgTfuHqInfo          *fdbk,
1868  U8                   tbIdx,
1869  RgSchTddANInfo       *anInfo,
1870  U8                   M,
1871  CmLteTimingInfo      timeInfo
1872  )
1873 #else
1874 PRIVATE Void rgSchGetHqFdbkPosForM234(ue,hqP,isAck,fdbk,tbIdx,anInfo,M,timeInfo)
1875  RgSchUeCb            *ue;
1876  RgSchDlHqProcCb      *hqP;
1877  U8                  *isAck;
1878  RgTfuHqInfo          *fdbk;
1879  U8                   tbIdx;
1880  RgSchTddANInfo       *anInfo;
1881  U8                    M;
1882  CmLteTimingInfo      timeInfo;
1883 #endif
1884 {
1885    U8                   fdbkIdx;
1886    Bool                 isSCell;
1887    RgSchTddANInfo       *pCellAnInfo;
1888    U8                   incr = 0;
1889
1890    if(NULLP != ue)
1891    {
1892       isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1893       pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1894
1895       if(TRUE == fdbk->isPusch)
1896       {
1897          if(TRUE == isSCell) 
1898          {/*SCell*/
1899             if (anInfo->wUlDai == 3)
1900             {
1901                incr = anInfo->wUlDai;
1902             }
1903             else
1904             {
1905                incr = M;
1906             }
1907             if(1 == anInfo->ulDai)
1908             {
1909                fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + 
1910                   hqP->tbInfo[tbIdx].tbIdx + incr;
1911             }
1912             else
1913             {
1914                fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1915             }
1916          }
1917          else
1918          {/*PCell*/
1919             if(1 == anInfo->ulDai)
1920             {
1921                if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1922                {
1923                   fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1924                }
1925                else
1926                {
1927                   fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1; 
1928                }
1929             }
1930             else
1931             {
1932                fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1; 
1933             }
1934          }
1935       }
1936       else
1937       {/*PUCCH*/
1938          if(TRUE == isSCell) 
1939          {
1940             /* pucchFdbkIdx is set to DAI hence -1 to get index */
1941             fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1); 
1942          }
1943          else
1944          {
1945             if(M > 2)
1946             {
1947                /* SPS occasion feedback in case of M > 2 will
1948                 * be always present in the index 0*/
1949 #ifdef LTEMAC_SPS
1950                if(hqP->spsN1PucchRes.pres == TRUE)
1951                {/* SPS occasion hq proc */
1952                   fdbkIdx = 0;
1953                }else 
1954 #endif
1955                if((NULLP != pCellAnInfo) && 
1956                      (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1957                {
1958                   fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx; 
1959                }else
1960                {/* NO SPS occasion was present in the bundle*/
1961                   fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1; 
1962                }
1963             }
1964             else
1965             {
1966                fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1; 
1967             }
1968          }
1969       }
1970       *isAck = fdbk->isAck[fdbkIdx];
1971 #ifdef DLHQ_STATS
1972       static RgSchDlHqProcCb      *temp = NULLP;
1973       if (temp != hqP->tbInfo[tbIdx].hqP)
1974       {
1975          statsCnt = statsCnt % 10000;
1976          dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
1977          dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn; 
1978          dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot; 
1979          dlHqStats[statsCnt].ack = *isAck;
1980          dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
1981          dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;;
1982          if (anInfo)
1983             dlHqStats[statsCnt].ulDai = incr;
1984          if(TRUE == fdbk->isPusch)
1985          {
1986             dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
1987          }
1988          else
1989          {
1990             dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1991          }
1992          if (*isAck != 1)
1993          {
1994             dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
1995             dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
1996             dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
1997             dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
1998             dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
1999             dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
2000             dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
2001             dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
2002          }
2003          statsCnt++; 
2004          temp = hqP->tbInfo[tbIdx].hqP;
2005       }
2006 #endif
2007    }/*ue*/
2008    RETVOID;
2009 }/*rgSchGetHqFdbkPosForM234*/
2010 #endif/*LTE_ADV*/
2011
2012 /*
2013  * @brief Handler for HARQ feedback received for DL transmission.
2014  *
2015  * @details
2016  *
2017  *     Function : rgSCHDhmHqFdbkInd
2018  *
2019  *     This function shall act on the feedback received from TOM for DL
2020  *     transmission. If the feedback for msg4 is final (after max transmissions
2021  *     or ACK) inform RAM that Msg4 transmission is done.
2022  *
2023  *
2024  *  @param[in]  Void                *cb
2025  *  @param[in]  U8                  cbType
2026  *  @param[in]  RgSchCellCb         cellCb
2027  *  @param[in]  CmLteTimingInfo     timeInfo 
2028  *  @param[in]  TfuHqInfo           *fdbk
2029  *  @param[in]  RgInfRlsHqInfo      *rlsHqBufs
2030  *  @param[in]  RgSchErrInfo        *err
2031  *  @return     S16
2032  *      -# ROK
2033  *      -# RFAILED
2034  **/
2035 #ifdef ANSI
2036 S16 rgSCHDhmHqFdbkInd
2037 (
2038 Void                 *cb,
2039 U8                   cbType,
2040 RgSchCellCb          *cellCb,
2041 CmLteTimingInfo      timeInfo,
2042 TfuHqInfo            *fdbk,
2043 RgInfRlsHqInfo       *rlsHqBufs,
2044 RgSchErrInfo         *err
2045 )
2046 #else
2047 S16 rgSCHDhmHqFdbkInd(cb, cbType, cellCb, timeInfo, fdbk, rlsHqBufs, err)
2048 Void                    *cb;
2049 U8                      cbType;
2050 RgSchCellCb             *cellCb;
2051 CmLteTimingInfo         timeInfo;
2052 TfuHqInfo               *fdbk;
2053 RgInfRlsHqInfo          *rlsHqBufs;
2054 RgSchErrInfo            *err;
2055 #endif
2056 {
2057    RgSchCellCb *sCell = NULLP;
2058    RgSchDlHqEnt      *hqE;
2059    /*ccpu00127339 - MOD - change to avoid the crash*/
2060    RgSchUeCb         *ue = NULLP;
2061    RgSchDlSf         *sf;
2062    Bool              isMsg4 = FALSE;
2063    RgSchRaCb         *raCb = NULLP;
2064    U16               rnti=0;
2065    /* Maximum possible HARQ processes in UL-DL configuration 5 that is
2066     * given feedback at a time */
2067    RgSchDlHqProcCb   *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5];  /*MAX 5 Cells*/
2068    U8                numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
2069    S8                tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
2070    U8                hqCnt;
2071    U8                idx;
2072    RgSchTddANInfo    *anInfo = NULLP;
2073    U8                isAck = 0;
2074    U8                tbCnt;
2075    RgrTddAckNackMode ackNackMode;
2076    Bool              hqRls = FALSE;
2077    RgSchDlSf         *nxtDlsf = NULLP;
2078    /* U8                rcvCnt = 0; */
2079    CmLteTimingInfo   nxtfrm = {0,0};
2080    Bool              anUpd = FALSE;
2081    Bool              maxHqRetxReached;
2082 #ifdef LTEMAC_SPS
2083    Bool              hasRelPdcch = FALSE;
2084 #endif
2085
2086 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2087    RgSchTddDlAscSetIdxK    ascIdx;
2088    U8                      noFdbks;
2089 #endif
2090
2091 #ifdef LTEMAC_SPS_AN_MUX
2092    Bool                    isPusch   = FALSE;   
2093    U8                      tmpIdx;
2094    U8                      hIdx;   
2095    /* Subframes in which transmissions are scheduled and whose feedback can come
2096     * in this subframe. Used only for Multiplexing mode */
2097    CmLteTimingInfo         schdSfTime[RGSCH_TDD_MAX_FDBK];
2098 #ifdef RGSCH_SPS_STATS
2099    RgSchCmnDlHqProc        *cmnHqDl;
2100 #endif
2101 #endif
2102 #ifdef LTE_ADV
2103    U8                  sCellActCePres = 0;
2104 #endif
2105 /* LTEMAC_SPS_AN_MUX*/
2106    RgrSchFrmt1b3TypEnum uciFrmtTyp  = RG_SCH_UCI_FORMAT1A_1B; 
2107
2108    if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
2109    {
2110       raCb     = (RgSchRaCb *)(cb);
2111       ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
2112       hqE      = raCb->dlHqE;
2113       /* ccpu00139061 Fix */
2114       rnti     = raCb->tmpCrnti;
2115    }
2116    else
2117    {
2118       ue       = (RgSchUeCb *)(cb);
2119       ackNackMode = ue->dl.ackNackMode;
2120       hqE      = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
2121       rnti     = ue->ueId;
2122 #ifdef LTEMAC_SPS_AN_MUX
2123       isPusch = fdbk->isPusch;
2124 #endif
2125
2126 #ifdef LTEMAC_SPS      
2127       if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
2128       {
2129          hasRelPdcch = TRUE;
2130       }
2131 #endif
2132    }
2133    
2134 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2135    ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
2136    noFdbks = ascIdx.numFdbkSubfrms;
2137 #endif
2138 #ifdef LTEMAC_SPS_AN_MUX
2139    /* Calculate the subframe time at which transmissions should have happened to
2140     * receive feedback in this subframe */
2141    if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2142    {
2143       for(idx=0; idx<noFdbks; idx++)
2144       {
2145          /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output 
2146           * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is 
2147           * serving the purpose */
2148           RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
2149       }
2150    }
2151 #endif
2152
2153    rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
2154                             tbStrtIdx, &hqCnt,hqE->cell);
2155    /* Fetch the harqProc from the inUse list */
2156 #ifdef LTEMAC_SPS
2157    if ((FALSE == hasRelPdcch) && (hqCnt == 0))
2158 #endif
2159    if(hqCnt == 0)
2160    {
2161       err->errType   = RGSCHERR_DHM_FDBK_IND;
2162       err->errCause  = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2163       return RFAILED;
2164    }
2165
2166    /* ccpu00147469 : This code is moved below as here this code always try to
2167     * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
2168     * cellId of PCEll
2169     */
2170
2171    if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
2172    {
2173       rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);    
2174    }
2175
2176 #ifdef TFU_TDD
2177 #endif
2178
2179 #ifdef LTEMAC_SPS_AN_MUX
2180    /* Check if feedback came on configured UL SPS grant in Muxing mode */
2181   if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) && 
2182         (isPusch == TRUE) )
2183    {
2184       hIdx = 0;
2185       /* Pick the valid feedbacks out of M feedbacks */
2186       for(idx=0; idx<noFdbks; idx++)
2187       {
2188          /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx] 
2189           * and no release pdcch is sent in prevTime */
2190          /* TODO: SPS_TDD: Check this while testing */
2191          if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
2192                      tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
2193                         schdSfTime[idx])) &&
2194                !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
2195          { 
2196             /* Discard the feedback which is corresponding to a subframe in
2197              * which no DL transmission took place */
2198             tmpIdx = idx+1;
2199             while(tmpIdx < noFdbks)
2200             {
2201                fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2202                fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2203                tmpIdx++;
2204             }
2205             rcvCnt--;
2206             ++hIdx;
2207          }
2208       } /* end of for loop */
2209    } /* end of configured UL SPS grant check */
2210 #endif   
2211 #ifdef CA_DBG
2212   {
2213      if(ue)
2214      {
2215         gHqFdbkCount++;
2216      }
2217   }
2218
2219 #endif   
2220
2221   for(idx=0;idx < hqCnt; idx++)
2222   {
2223      /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
2224      if(ue)
2225      {
2226 #ifdef LTE_ADV
2227         U8 servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
2228         hqPrcs[idx]->hqE->cell->cellId,ue);
2229
2230         if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)  
2231         {
2232            continue; 
2233         }
2234         anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
2235 #else
2236         anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
2237 #endif
2238         if(anInfo == NULLP)
2239         {
2240            RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx), 
2241                     "Ack Rcvd. No Ack/Nack feedback available \n"));
2242            return RFAILED;
2243         }
2244      }
2245
2246      sCell = hqPrcs[idx]->hqE->cell;
2247      rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2248      rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2249      for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2250      {
2251         /* Fix : syed MultiUe per TTI crash in TA List. */
2252         hqRls = FALSE;
2253         maxHqRetxReached = FALSE;
2254         /* Remove the harq process from the subframe */
2255         sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2256
2257         if(NULLP != ue)
2258         {
2259            uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2260         }
2261
2262         if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2263         {
2264            if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2265                  (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2266            {
2267               isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2268            }
2269            else
2270            {
2271               /* TODO: review for TM4 and CA interaction */
2272               if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2273               {
2274                  isAck = fdbk->isAck[!tbCnt];
2275               }
2276               else
2277               {
2278                  isAck = fdbk->isAck[tbCnt];
2279               } 
2280            }
2281         }
2282 #ifdef LTE_ADV
2283         else
2284         {
2285               if(1 == noFdbks)
2286               {/* M == 1 case */
2287                  rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo); 
2288               }
2289               else
2290               {
2291                  rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo); 
2292               }
2293         }
2294 #endif
2295
2296 #ifdef BRDCM
2297          /* revanth tweakin AN PUSCH to ACK always */
2298          if (hqPrcs[idx]->isPuschFdbk)
2299          {
2300             isAck = 1;
2301          }
2302 #endif
2303
2304          hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2305          if(cellCb->ulDlCfgIdx != 5)
2306          {
2307             rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2308                                    cellCb, sf, &nxtDlsf, &nxtfrm);
2309          }
2310          /* Keep a tab on how many ACKs or NACKs we have received */
2311          if (isAck == TFU_HQFDB_ACK)
2312          {
2313             hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */ 
2314             rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2315 #ifdef TENB_STATS
2316             sCell->tenbStats->sch.dlAckNack[tbCnt]\
2317                [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2318 #endif
2319             /* Do not update the Ul Trans Time in case of raCb */
2320             if (ue)
2321             { 
2322                rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2323 #ifdef TENB_STATS
2324                ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2325 #endif
2326             }
2327          }
2328          else if (isAck == TFU_HQFDB_NACK)
2329          {
2330             hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */ 
2331             rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2332 #ifdef TENB_STATS
2333             sCell->tenbStats->sch.dlNack[tbCnt]\
2334                [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2335             sCell->tenbStats->sch.dlAckNack[tbCnt]\
2336                [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2337 #endif
2338             /* Do not update the Ul Trans Time in case of raCb */
2339             if (ue)
2340             { 
2341                rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2342 #ifdef TENB_STATS
2343                ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2344                ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2345 #endif
2346             }
2347 #ifdef LTE_L2_MEAS           
2348             if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2349             {
2350                cellCb->dlUlTbCnt.tbTransDlFaulty++; 
2351             }   
2352 #endif            
2353          }
2354          else
2355          {
2356             hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1;  /* DTX Counter*/
2357 #ifdef TENB_STATS
2358             sCell->tenbStats->sch.dlDtx[tbCnt]\
2359                [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2360             if (ue)
2361             {
2362                ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2363             }
2364 #endif
2365 #ifdef LTE_L2_MEAS           
2366             if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2367             {
2368                cellCb->dlUlTbCnt.tbTransDlFaulty++; 
2369             }   
2370 #endif            
2371          }
2372 #ifdef CA_DBG
2373          if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2374          {
2375             if(isAck == TFU_HQFDB_ACK)
2376             {
2377                gSCellTb1AckCount++;
2378                gSCellTb2AckCount++;
2379             }else if(isAck == TFU_HQFDB_NACK)
2380             {
2381                gSCellTb1NackCount++;
2382                gSCellTb2NackCount++;
2383             }else
2384             {
2385                gSCellTb1DtxCount++;
2386                gSCellTb2DtxCount++;
2387             }
2388          }
2389          else
2390          {
2391             if(isAck == TFU_HQFDB_ACK)
2392             {
2393                gPCellTb1AckCount++;
2394                gPCellTb2AckCount++;
2395             }else if(isAck == TFU_HQFDB_NACK)
2396             {
2397                gPCellTb1NackCount++;
2398                gPCellTb2NackCount++;
2399             }else
2400             {
2401                gPCellTb1DtxCount++;
2402                gPCellTb2DtxCount++;
2403             }
2404          }
2405 #endif
2406          /* Check if this is repeating UE */
2407          if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2408          {
2409             rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2410             /* Check if last repetition */
2411             if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2412             {
2413                RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2414                /* Update feedback time for this hqP TB so that 
2415                 * next subframe its picked up */
2416                RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2417                                        nxtDlsf, nxtfrm);
2418                RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2419                RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2420                anUpd = TRUE;
2421                continue;
2422             }
2423             /* For a repeating UE take the decision here */
2424             /* For a repeating UE take the decision here */
2425             if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) && 
2426                ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2427             {
2428                isAck = TFU_HQFDB_ACK; 
2429             }
2430             else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) && 
2431                   ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2432             {
2433                isAck = TFU_HQFDB_DTX; 
2434             }
2435             else
2436             {
2437                isAck = TFU_HQFDB_NACK; 
2438             }
2439             hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2440          }
2441          else
2442          {
2443             rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2444          }
2445 #ifdef LTEMAC_SPS
2446          if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2447                ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2448                 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2449             )
2450          {
2451             /* ACK or NACK received for SPS ACTV PDCCH
2452              * Hence consider SPS ACTVN PDCCH received successfully */
2453             rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2454          }
2455 #endif
2456          if(TFU_HQFDB_ACK == isAck)
2457          {
2458             /* SPS_REVIEW */
2459             if (isMsg4 == TRUE)
2460             {
2461                if (raCb == NULLP)
2462                {
2463                   raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2464                }
2465                /* Inform Random Access Module regarding the ack received */
2466                if (raCb != NULLP)
2467                {
2468                   /*RRC Connection Setup failure issue where RRC connection
2469                    * setup was not reaching UE due to message 4 HARQ failure */
2470 #ifdef XEON_SPECIFIC_CHANGES
2471                   CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2472 #endif 
2473                   rgSCHRamMsg4Done(cellCb, raCb);
2474                }
2475             }
2476             else /*ccpu00114124- HARQ Release for Msg4 */
2477             {
2478 #ifdef DL_LA
2479                /*Update feedback history for every Tx/Retx */
2480                   rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2481 #endif
2482                RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2483                RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2484 #ifdef LTE_ADV
2485                /* Store activation CE presence as it is required later to start
2486                 *activation delay timer */
2487                sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres; 
2488 #endif
2489                rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2490             }
2491             hqRls = TRUE;
2492          }
2493          else
2494          {
2495             /* If this Msg4 DTX, there will be 
2496              * no DlHqProc as it has its own HarqProc */
2497              /* SPS_REVIEW */
2498             {
2499                rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2500                maxHqRetxReached = hqRls;
2501 #ifdef DL_LA
2502                if ((isMsg4 == FALSE))
2503                {
2504                   /*Update feedback history for every Tx/Retx */
2505                   rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2506                }
2507 #endif
2508                if (isMsg4 == FALSE)
2509                {
2510                   RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2511                   RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2512                }
2513             }
2514          }
2515
2516          if(TRUE == hqRls)
2517          {
2518      /* MS_WORKAROUND: to increase Harq Fail Counter .
2519        The status field is required for tracking the number of harq faliures at MAC*/
2520          if (isAck)
2521          {
2522             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2523                rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2524          }
2525          else
2526          {
2527             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2528                rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2529          }
2530             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2531             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2532             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2533          }
2534
2535          /* Handle the TA */
2536          if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2537          {
2538             rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2539          }
2540 #ifdef LTE_ADV
2541          /* Handle Scell activation */
2542          if (TRUE == sCellActCePres)
2543          {
2544             /* Primary Cellcb needs to be retrived
2545              * if the feedback is coming on pusch of 
2546              * sec cell. THis needs to be considered
2547              * while UL_CA*/
2548             rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2549          }
2550 #endif
2551       }
2552      if (hqRls == FALSE)
2553      {
2554         hqPrcs[idx]->cwSwpEnabled = FALSE;
2555      }
2556       if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2557       {
2558          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2559          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = 
2560             hqPrcs[idx]->procId;
2561          rlsHqBufs->numUes++;
2562       }
2563 #ifdef BRDCM
2564       hqPrcs[idx]->isPuschFdbk = 0;
2565 #endif
2566    }
2567
2568 #ifdef LTEMAC_SPS
2569   /*it is possible for some TDD configurations (like TDD cfg 5) 
2570    * to have multiple feedback for 13 subframes before. It is 
2571    * possible in such a case to have a release sent after data
2572    * thus running into a situation where we are receiving feedback
2573    * for both data and relese pdcch 
2574    */
2575 /*
2576    if ( (hqCnt == 0) ||
2577         (hasRelPdcch && rcvCnt > hqCnt)
2578       ) 
2579       */
2580    if (ue && hasRelPdcch)   
2581    {
2582       /* Bool found      = FALSE; */
2583       
2584       sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2585
2586       /*
2587       if ( !sf->relPdcch)
2588       {
2589          found = FALSE;
2590       } 
2591       */
2592
2593       
2594 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2595       if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2596       {
2597          CmLteTimingInfo txTime;
2598          U8   ulDlCfgIdx = 0;
2599          U8   maxFdbks   = 0;
2600          U8   itr        = 0;
2601
2602          ulDlCfgIdx  = cellCb->ulDlCfgIdx;
2603
2604          maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2605             [timeInfo.slot].
2606             numFdbkSubfrms;
2607
2608          for(itr=0; itr< maxFdbks; itr++)
2609          {
2610 #ifdef LTE_ADV
2611             /* Handling the case of only SPS release pdcch
2612              * and no other scheduling in both the serving cells
2613              * */
2614             if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2615             {/* Using the sorted K table */
2616                RGSCHDECRFRMCRNTTIME (timeInfo, txTime, 
2617                      rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2618             }else
2619 #endif
2620             {
2621                RGSCHDECRFRMCRNTTIME (timeInfo, txTime, 
2622                      rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2623             }
2624
2625             if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2626             {
2627 #ifdef LTE_ADV
2628                if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2629                      (maxFdbks == 1))
2630                {/* M == 1 case */
2631                   if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2632                   {
2633                      isAck = fdbk->isAck[0];
2634                   }else
2635                   {
2636                      isAck = fdbk->isAck[2];
2637                   }
2638                }
2639                else
2640                   /* M > 1 same below logic apply. 
2641                      If SPS occasion and rel pdcch is present
2642                      SPS occasion after SPS release cannot 
2643                      happen in a bundle
2644                      */
2645 #endif
2646                {
2647                   isAck = fdbk->isAck[itr];
2648                }
2649                
2650                rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2651
2652                RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2653                /* Remove release PDCCH from the subframe */
2654                rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2655                sf->relPdcch = NULLP;
2656                /* found = TRUE; */
2657                break;
2658             }
2659
2660          }
2661       }
2662       else
2663 #endif
2664       {
2665          RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2666          /* Remove release PDCCH from the subframe */
2667          rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2668          sf->relPdcch = NULLP;
2669          /* found = TRUE; */
2670          rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2671       }
2672       /*
2673          if ( found == FALSE ) 
2674          {
2675          RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2676          RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,"CRNTI:%d"
2677          " NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2678          ue->ueId,timeInfo.sfn, timeInfo.slot);
2679          err->errType   = RGSCHERR_DHM_FDBK_IND;
2680          err->errCause  = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2681          return RFAILED;
2682          }
2683        */
2684    }/*if(hqCnt==0)*/
2685 #endif /* LTEMAC_SPS */
2686    /* Initialise the Ack/Nack feedback */
2687    /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while 
2688       scheduling. So added a condition !isMsg4 to avoid calling the function 
2689       rgSCHUtlInitUeANFdbkInfo*/
2690    if((ue) && (!anUpd) && (!isMsg4))
2691    {
2692 #ifdef LTE_ADV
2693       /* TODO:: Initi the anInfo all the serving cells */
2694       for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2695       {
2696          if(ue->cellInfo[idx])
2697          {
2698             anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2699             /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2700              * else don't do anything. basically continue for next serving
2701              * cell*/
2702             if(anInfo)
2703             {
2704                rgSCHUtlInitUeANFdbkInfo(anInfo);
2705             }
2706          }
2707       }
2708 #else
2709       rgSCHUtlInitUeANFdbkInfo(anInfo);
2710 #endif
2711    }
2712
2713    return ROK;
2714 }
2715 //#endif /* LTEMAC_SPS */
2716
2717 #else /* LTE_TDD */
2718 /** * @brief Handler for HARQ feedback received for DL transmission.
2719  *
2720  * @details
2721  *
2722  *     Function : rgSCHDhmPrcFdbkForTb
2723  *     
2724  *                Process Hq Prc Fdbk for a TB
2725  *           
2726  *  @param[in]  RgSchCellCb         *cell
2727  *  @param[in]  RgTfuHarqAckIndInfo *fdbk
2728  *  @param[in]  RgSchErrInfo        *err
2729  *  @return     S16
2730  *      -# ROK 
2731  *      -# RFAILED 
2732  **/
2733 #ifdef ANSI
2734 S16 rgSCHDhmPrcFdbkForTb
2735 (
2736 RgSchCellCb          *cell,
2737 RgSchUeCb            *ue,
2738 RgSchDlHqProcCb      *hqP,
2739 RgSchDlSf            *sf,
2740 Bool                 isMsg4,
2741 U16                  rnti,
2742 U8                   tbCnt,
2743 CmLteTimingInfo      timingInfo,
2744 U8                   isAck,
2745 RgInfRlsHqInfo       *rlsHqBufs,
2746 RgSchErrInfo         *err
2747 )
2748 #else
2749 S16 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt, timingInfo, isAck, rlsHqBufs, err)
2750 RgSchCellCb             *cell;
2751 RgSchUeCb               *ue;
2752 RgSchDlHqProcCb         *hqP;
2753 RgSchDlSf               *sf;
2754 Bool                    isMsg4;
2755 U16                     rnti;
2756 U8                      tbCnt;
2757 CmLteTimingInfo         timingInfo;
2758 U8                      isAck;
2759 RgInfRlsHqInfo          *rlsHqBufs;
2760 RgSchErrInfo            *err;
2761 #endif
2762 {
2763 #ifdef DEBUGP
2764    Inst    inst = cell->instIdx;
2765 #endif
2766 #ifdef RGSCH_SPS_STATS
2767    RgSchCmnDlHqProc        *cmnHqDl;
2768 #endif
2769    S16                  ret = ROK;
2770    RgSchRaCb            *raCb = NULLP;
2771    Bool                 hqRls=FALSE;
2772    Bool                 hqFreed =FALSE;
2773    Bool                 maxHqRetxReached = FALSE;
2774    RgSchCmnDlUe         *ueDl = NULLP;
2775    RgSchCellCb          *sCell = hqP->hqE->cell;
2776 #ifdef EMTC_ENABLE
2777    RgSchEmtcDlSf        *emtcSf;
2778    CmLteTimingInfo      frm = timingInfo;
2779 #endif
2780
2781    if (ue)
2782    {
2783       ueDl     = RG_SCH_CMN_GET_DL_UE(ue,cell);
2784    }
2785    hqRls   = FALSE;
2786    /* Fix : syed MultiUe per TTI crash in TA List. */
2787    maxHqRetxReached = FALSE;
2788
2789    /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2790     * TODO: Need to enhance this in case of TM4 testing,
2791     * when cwSwap flag is considered. */
2792
2793    RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2794             tbCnt=%d , isAck=%d",tbCnt,isAck));
2795    if (isAck == TFU_HQFDB_ACK)
2796    {
2797       hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2798       /*sanjay*/
2799       rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2800       /* Do not update the Ul Trans Time in case of raCb */
2801       if (ue)
2802       { 
2803          rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2804 #ifdef TENB_STATS
2805          ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2806 #endif
2807
2808       }
2809
2810 #ifdef TENB_STATS
2811       sCell->tenbStats->sch.dlAckNack[tbCnt]\
2812          [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2813
2814 #endif
2815
2816    }
2817    else if (isAck == TFU_HQFDB_NACK)
2818    {
2819       hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2820       RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2821                "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2822       rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2823       /* Do not update the Ul Trans Time in case of raCb */
2824
2825 #ifdef TENB_STATS
2826       sCell->tenbStats->sch.dlAckNack[tbCnt]\
2827          [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2828       
2829       sCell->tenbStats->sch.dlNack[tbCnt]\
2830          [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2831
2832
2833 #endif
2834
2835       if (ue)
2836       { 
2837          rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2838 #ifdef TENB_STATS
2839          ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2840          ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2841 #endif
2842       }
2843       /* Added Dl TB count for NACKED data*/
2844 #ifdef LTE_L2_MEAS
2845       if(hqP->tbInfo[tbCnt].txCntr == 1)
2846       {   
2847          cell->dlUlTbCnt.tbTransDlFaulty++;
2848       }   
2849 #endif         
2850    }
2851    else
2852    {
2853       RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2854                hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2855       hqP->tbInfo[tbCnt].dtxCount += 1;  /* DTX Counter*/
2856
2857 #ifdef TENB_STATS
2858       sCell->tenbStats->sch.dlDtx[tbCnt]\
2859          [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2860       if (ue)
2861       {
2862          ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2863       }
2864 #endif
2865
2866
2867       /* Added Dl TB count for DTXED data*/
2868 #ifdef LTE_L2_MEAS
2869       if(hqP->tbInfo[tbCnt].txCntr == 1)
2870       {   
2871          cell->dlUlTbCnt.tbTransDlFaulty++;
2872       }
2873 #endif         
2874    }
2875
2876    /* Check if this is repeating UE */
2877    if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2878    {
2879       if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2880       {
2881          return (ret);
2882       }
2883    }
2884    else
2885    {
2886      /* For a Normal UE take the decision here */
2887      hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2888      {
2889          rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2890      }
2891    }
2892    /* Process either the ACK received or max retries have occurred */
2893    /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2894    if (TFU_HQFDB_ACK == isAck)
2895    {
2896       if (isMsg4 == TRUE) 
2897       {
2898          /* SR_RACH_STATS : MSG4 ACK*/
2899          rgNumMsg4Ack++;
2900
2901          if (raCb == NULLP)
2902          {
2903             raCb = rgSCHDbmGetRaCb(cell, rnti);
2904          }
2905          RGSCHDBGINFO(cell->instIdx,
2906                (rgSchPBuf(cell->instIdx), "Ack Rcvd. FdbkInd for Msg4Done\n"));
2907          /* Inform Random Access Module regarding the ack received */
2908          if (raCb != NULLP)
2909          {
2910             /*RRC Connection Setup failure issue where RRC connection 
2911              * setup was not reaching UE due to message 4 HARQ failure */
2912             printf("\nMSG4 Ack ,calling rgSCHRamMsg4Done\n");
2913             ret = rgSCHRamMsg4Done(cell, raCb);
2914             hqFreed = TRUE;
2915          }
2916          else
2917          {
2918             printf("\nraCb is NULLP\n");
2919          }
2920       }
2921       else /*ccpu00114124- HARQ Release for Msg4 */
2922       {
2923          RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2924          /* Push this harq process back to the free queue */
2925          ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2926 #ifdef DL_LA
2927          if(hqP->tbInfo[tbCnt].txCntr == 1)
2928          {
2929             rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2930          } 
2931 #endif
2932          RGSCH_NULL_CHECK(cell->instIdx, ue);
2933          RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2934          rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2935       }
2936       hqRls = TRUE;
2937    }
2938    else
2939    {
2940       {
2941          if(!isMsg4)
2942          {
2943             RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2944             ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2945 #ifdef DL_LA
2946             if(hqP->tbInfo[tbCnt].txCntr == 1)
2947             {
2948                rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2949             }
2950 #endif
2951             RGSCH_NULL_CHECK(cell->instIdx, ue);
2952             RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2953          }
2954          else
2955          { 
2956 #ifdef XEON_SPECIFIC_CHANGES
2957             CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2958 #endif
2959             rgNumMsg4Nack++;
2960          }
2961          rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2962          maxHqRetxReached = hqRls;
2963       }
2964    }
2965
2966    if(hqRls == TRUE)
2967    {
2968       /* MS_WORKAROUND: to increase Harq Fail Counter .
2969          The status field is required for tracking the number of harq faliures at MAC*/
2970       if (isAck)
2971       {
2972          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2973             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2974       }
2975 #ifdef LTE_L2_MEAS
2976       else if(maxHqRetxReached)
2977       {
2978          /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
2979          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2980             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
2981       }
2982 #endif
2983       else
2984       {
2985          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2986             rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2987       }
2988       rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2989          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2990       rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2991    }
2992
2993    /* Handle the TA */
2994    if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
2995    {
2996       rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
2997    }
2998    return (ret);
2999 }  /* rgSCHDhmPrcFdbkForTb */
3000 /** * @brief Function to decode the position of HarqFb for eachCell.
3001  *
3002  * @details
3003  *
3004  *     Function : rgSchGetHqFdbkPos
3005  *           
3006  *  @param[in]  RgSchCellCb          *cell,
3007  *  @param[in]  RgSchUeCb            *ue,
3008  *  @param[in]  RgSchDlHqProcCb      *hqP,
3009  *  @param[in]  RgrSchFrmt1b3TypEnum uciFrmtTyp, 
3010  *  @param[in]  Bool                 *isAck, 
3011  *  @param[in]  RgTfuHqInfo          *fdbk,
3012  *  @return     RETVOID
3013  **/
3014 #ifdef ANSI
3015 Void rgSchGetHqFdbkPos
3016 (
3017  RgSchCellCb          *cell,
3018  RgSchUeCb            *ue,
3019  RgSchDlHqProcCb      *hqP,
3020  RgrSchFrmt1b3TypEnum uciFrmtTyp, 
3021  U8                  *isAck, 
3022  RgTfuHqInfo          *fdbk
3023  )
3024 #else
3025 Void rgSchGetHqFdbkPos(cell,ue,hqP,uciFrmtTyp,isAck,fdbk)
3026  RgSchCellCb          *cell;
3027  RgSchUeCb            *ue;
3028  RgSchDlHqProcCb      *hqP;
3029  RgrSchFrmt1b3TypEnum uciFrmtTyp;
3030  U8                  *isAck;
3031  RgTfuHqInfo          *fdbk;
3032 #endif
3033 {
3034    if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
3035    {
3036       isAck[0] = fdbk->isAck[0];
3037       isAck[1] = fdbk->isAck[1];
3038       RETVOID;
3039    }
3040 #ifdef LTE_ADV
3041    /* LAA Making all ack for LAA CELL */
3042    //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
3043    if (0)
3044    {
3045       isAck[0] = TRUE;
3046       isAck[1] = TRUE;
3047       RETVOID;
3048    }
3049
3050    if((ue != NULLP))
3051    {
3052       /* PUSCH:: Fdbks are in the increasing order
3053        * of servCellIdx as per 36.212 section 5.2.26*/
3054       switch(ue->f1bCsAVal)
3055       {/* A Value */
3056          case RG_SCH_A_VAL_2:
3057             {
3058                if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
3059                {
3060                   isAck[0] = fdbk->isAck[1];/*SCell*/
3061                   isAck[1] = fdbk->isAck[1];/*SCell*/
3062                }
3063                else
3064                {
3065                   isAck[0] = fdbk->isAck[0];/*PCell*/
3066                   isAck[1] = fdbk->isAck[0];/*PCell*/
3067                }
3068                break;
3069             }
3070          case RG_SCH_A_VAL_3:
3071             {
3072                if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
3073                {
3074 #ifdef LTE_ADV
3075                   U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
3076                         hqP->hqE->cell->cellId,
3077                         ue);
3078
3079                   if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
3080 #else
3081                      if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
3082 #endif
3083                      {  /* Sec cell is in mimo mode */
3084                         /* use 0 and 1 for sec in case of pucch
3085                          * and 1 and 2 in case of PUSCH as the primary cell is in
3086                          * siso case as A =3 */
3087                         if(!fdbk->isPusch)
3088                         {
3089                            isAck[0] = fdbk->isAck[0];
3090                            isAck[1] = fdbk->isAck[1];
3091                         }else
3092                         {/* PUSCH as per 36.212 serction 5.2.26*/
3093                            isAck[0] = fdbk->isAck[1];
3094                            isAck[1] = fdbk->isAck[2];
3095                         }
3096                      }else
3097                      {/* sec cell is in siso */
3098                         isAck[0] = fdbk->isAck[2];
3099                      }
3100                }else
3101                {
3102                   if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3103                   {/* primay cell is in mimo
3104                       use 0 and 1 */
3105                      isAck[0] = fdbk->isAck[0];
3106                      isAck[1] = fdbk->isAck[1];
3107                   }else
3108                   {
3109                      if(!fdbk->isPusch)
3110                      {
3111                         isAck[0] = fdbk->isAck[2];
3112                      }else
3113                      {/* PUSCH as per 36.212 serction 5.2.26*/
3114                         isAck[0] = fdbk->isAck[0];
3115                      }
3116                   }
3117                }
3118                break;
3119             }
3120          case RG_SCH_A_VAL_4:
3121             {
3122                if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell)) 
3123                {
3124                   isAck[0] = fdbk->isAck[2];
3125                   isAck[1] = fdbk->isAck[3];
3126 #ifdef CA_DBG
3127                   {
3128                      if(isAck[0] == TFU_HQFDB_ACK)
3129                      {
3130                         gSCellTb1AckCount++;
3131                      }else if(isAck[0] == TFU_HQFDB_NACK)
3132                      {
3133                         gSCellTb1NackCount++;
3134                      }else
3135                      {
3136                         gSCellTb1DtxCount++;
3137                      }
3138
3139                      if(isAck[1] == TFU_HQFDB_ACK)
3140                      {
3141                         gSCellTb2AckCount++;
3142                      }else if(isAck[1] == TFU_HQFDB_NACK)
3143                      {
3144                         gSCellTb2NackCount++;
3145                      }else
3146                      {
3147                         gSCellTb2DtxCount++;
3148                      }
3149
3150                   }
3151 #endif
3152                }
3153                else
3154                {
3155                   isAck[0] = fdbk->isAck[0];
3156                   isAck[1] = fdbk->isAck[1];
3157 #ifdef CA_DBG
3158                   {
3159                      if(isAck[0] == TFU_HQFDB_ACK)
3160                      {
3161                         gPCellTb1AckCount++;
3162                      }else if(isAck[0] == TFU_HQFDB_NACK)
3163                      {
3164                         gPCellTb1NackCount++;
3165                      }else
3166                      {
3167                         gPCellTb1DtxCount++;
3168                      }
3169
3170                      if(isAck[1] == TFU_HQFDB_ACK)
3171                      {
3172                         gPCellTb2AckCount++;
3173                      }else if(isAck[1] == TFU_HQFDB_NACK)
3174                      {
3175                         gPCellTb2NackCount++;
3176                      }else
3177                      {
3178                         gPCellTb2DtxCount++;
3179                      }
3180
3181                   }
3182 #endif
3183
3184                }
3185                break;
3186             }
3187          default:
3188             break;
3189       }
3190    }
3191 #endif
3192    RETVOID;
3193 }/* End of rgSchGetHqFdbkPos */
3194 #ifdef LTE_ADV
3195 #ifdef ANSI
3196 Void rgSchGetHqFdbkPosFormat3
3197 (
3198  RgSchDlHqProcCb      *hqP,
3199  U8                   *isAck,
3200  TfuHqFdbk            *fdbk
3201  )
3202 #else
3203 Void rgSchGetHqFdbkPosFormat3(hqP,isAck,fdbk)
3204  RgSchDlHqProcCb      *hqP;
3205  U8                  *isAck;
3206  TfuHqFdbk           *fdbk;
3207 #endif
3208 {
3209    U8 cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
3210    isAck[0] = (U8)fdbk[cellIdx]; 
3211    isAck[1] = (U8)fdbk[cellIdx + 1]; 
3212 }
3213 #endif
3214 /** * @brief Handler for HARQ feedback received for DL transmission.
3215  *
3216  * @details
3217  *
3218  *     Function : rgSCHDhm5gtfHqFdbkInd 
3219  *     
3220  *     This function shall act on the feedback received from TOM for DL
3221  *     transmission. If the feedback for msg4 is final (after max transmissions
3222  *     or ACK) inform RAM that Msg4 transmission is done. 
3223  *     
3224  *           
3225  *  @param[in]  Void                *cb
3226  *  @param[in]  U8                  cbType
3227  *  @param[in]  RgSchCellCb         *cell
3228  *  @param[in]  RgTfuHarqAckIndInfo *fdbk
3229  *  @param[in]  RgInfRlsHqInfo      *rlsHqBufs
3230  *  @param[in]  RgSchErrInfo        *err
3231  *  @return     S16
3232  *      -# ROK 
3233  *      -# RFAILED 
3234  **/
3235 #ifdef ANSI
3236 S16 rgSCHDhm5gtfHqFdbkInd 
3237 (
3238 RgSchUeCb            *ue,
3239 RgSchCellCb          *cell,
3240 CmLteTimingInfo      timingInfo,
3241 TfuHqFdbk            fdbk,
3242 RgSchErrInfo         *err
3243 )
3244 #else
3245 S16 rgSCHDhm5gtfHqFdbkInd(ue, cell, timingInfo, fdbk, err)
3246 RgSchUeCb            *ue;
3247 RgSchCellCb          *cell;
3248 CmLteTimingInfo      timingInfo;
3249 TfuHqFdbk            fdbk;
3250 RgSchErrInfo         *err;
3251 #endif
3252 {
3253    RgSchDlHqProcCb      *hqP = NULLP;   
3254    CmLList              *node = NULLP;
3255    CmLListCp            *lnk; 
3256    S16                  ret = ROK;
3257    RgSchDlSf            *sf;
3258    Bool                 isMsg4 = FALSE;
3259    U16                  rnti=0;
3260    U16                  procId=0;
3261    U8                   hqPCount = 0;
3262    RgInfRlsHqInfo       *rlsHqBufs = NULLP;
3263
3264    RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4); 
3265
3266    sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3267
3268    lnk      = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3269    node     = lnk->first; 
3270    hqPCount = lnk->count;
3271    rnti     = ue->ueId;
3272
3273    while (hqPCount)
3274    {
3275       hqP = (RgSchDlHqProcCb *)node->node;
3276       node = node->next;
3277       rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3278       procId = hqP->procId;
3279
3280       rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3281
3282       if (HQ_TB_WAITING == hqP->tbInfo[0].state)
3283       {
3284          rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0, 
3285             timingInfo, fdbk, rlsHqBufs, err);
3286       }
3287       if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3288       {
3289          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3290          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = 
3291             (U8)procId;
3292          rlsHqBufs->numUes++;
3293       }
3294       hqPCount--;
3295    }
3296
3297    return (ret);
3298 }  /* rgSCHDhm5gtfHqFdbkInd */
3299
3300 /** * @brief Handler for HARQ feedback received for DL transmission.
3301  *
3302  * @details
3303  *
3304  *     Function : rgSCHDhmHqFdbkInd
3305  *     
3306  *     This function shall act on the feedback received from TOM for DL
3307  *     transmission. If the feedback for msg4 is final (after max transmissions
3308  *     or ACK) inform RAM that Msg4 transmission is done. 
3309  *     
3310  *           
3311  *  @param[in]  Void                *cb
3312  *  @param[in]  U8                  cbType
3313  *  @param[in]  RgSchCellCb         *cell
3314  *  @param[in]  RgTfuHarqAckIndInfo *fdbk
3315  *  @param[in]  RgInfRlsHqInfo      *rlsHqBufs
3316  *  @param[in]  RgSchErrInfo        *err
3317  *  @return     S16
3318  *      -# ROK 
3319  *      -# RFAILED 
3320  **/
3321 #ifdef ANSI
3322 S16 rgSCHDhmHqFdbkInd
3323 (
3324 Void                 *cb, 
3325 U8                   cbType,
3326 RgSchCellCb          *cell,
3327 CmLteTimingInfo      timingInfo,
3328 RgTfuHqInfo          *fdbk,
3329 RgInfRlsHqInfo       *rlsHqBufs,
3330 RgSchErrInfo         *err
3331 )
3332 #else
3333 S16 rgSCHDhmHqFdbkInd(cb, cbType, cell, timingInfo, fdbk, rlsHqBufs, err)
3334 Void                    *cb;
3335 U8                      cbType;
3336 RgSchCellCb             *cell;
3337 CmLteTimingInfo         timingInfo;
3338 RgTfuHqInfo             *fdbk;
3339 RgInfRlsHqInfo          *rlsHqBufs;
3340 RgSchErrInfo            *err;
3341 #endif
3342 {
3343    RgSchDlHqTbCb        *tbCb;
3344    RgSchDlHqEnt         *hqE = NULLP;
3345    RgSchDlHqProcCb      *hqP = NULLP;   
3346    CmLList              *node = NULLP;
3347    CmLListCp            *lnk; 
3348   /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3349    RgSchUeCb            *ue = NULLP;
3350
3351    S16                  ret = ROK;
3352    RgSchDlSf            *sf;
3353    Bool                 isMsg4 = FALSE;
3354    RgSchRaCb            *raCb = NULLP;
3355    U16                  rnti=0;
3356   /* Added Insure Fixes Of UR.Initialized procId  */
3357    U16                  procId=0;
3358    /* DTX Change: Bool is converted into U8*/
3359    U8                   isAck[2]={0}; /*Changed to Array of 2*/
3360    U8                   tbCnt;
3361    U8                   hqPCount = 0;
3362
3363 #ifdef LTEMAC_SPS
3364    CmLteTimingInfo      fdbkRcptTime = timingInfo;
3365 #ifdef RGSCH_SPS_STATS
3366    RgSchCmnDlHqProc        *cmnHqDl;
3367 #endif
3368 #endif
3369 #ifdef LTE_ADV
3370    TfuHqFdbk            format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3371 #endif
3372    RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3373
3374    /* Get the subframe associated with the feedback */
3375    /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output 
3376     * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is 
3377     * serving the purpose */
3378    RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4); 
3379
3380    sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3381    if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3382    {
3383       raCb     = (RgSchRaCb *)(cb);
3384       hqE      = raCb->dlHqE;
3385       hqP      = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3386                                       sf);
3387       if(hqP)
3388       {
3389          hqPCount = 1;
3390       }
3391       rnti     = raCb->tmpCrnti;
3392    }
3393    else
3394    {
3395       ue       = (RgSchUeCb *)(cb);
3396       hqE      = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3397       {
3398          lnk      = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3399       }
3400       node     = lnk->first; 
3401       hqPCount = lnk->count;
3402       rnti     = ue->ueId;
3403 #ifdef LTE_ADV
3404       uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3405 #endif
3406    }
3407    /*
3408       TO ADD STATS 
3409       from Harq Proc get ueCb = hqP->hqEnt->ueCb
3410       from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3411       from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3412       from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0] 
3413       from get CQI from cmInfo->cqi 
3414       from cmInfo get iTbs cmInfo->iTbs[0]
3415       call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS 
3416       Update stats in cellCb
3417       cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3418       if (fdbk->isAck == TRUE)
3419       cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3420       else
3421       cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3422       DL Ack/Nack statistics
3423     */   
3424 #ifdef MAC_SCH_STATS
3425    if (hqE->ue != NULLP)
3426    {
3427       RgSchUeCb      *ueCb  = hqE->ue;
3428       RgSchCmnUe     *cmnUe = (RgSchCmnUe*)ueCb->sch;
3429       RgSchCmnDlUe   *dlUe  = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3430       U8             tbs    = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3431       static U32 retxCnt    = 0;
3432
3433       if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3434       {
3435          hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3436       }
3437       else
3438       {
3439          ++retxCnt;
3440          hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3441       }
3442       RG_SCH_CMN_DL_TBS_TO_MCS(tbs, 
3443                (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3444    }
3445 #endif /* MAC_SCH_STATS */
3446
3447    /* Fetch the harqProc from the inUse list */
3448 #ifdef LTEMAC_SPS
3449    /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3450    /* Call Common module with the feedback information */
3451    if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3452    {
3453       if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3454       {
3455          sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3456
3457 #ifdef LTE_ADV
3458          if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3459          {/* Feedback for SPS Release on PCell
3460              If Pcell is in mimo, feedback index will be 0
3461              else 2 */
3462             if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3463             {
3464                isAck[0] = fdbk->isAck[0];
3465             }else
3466             {
3467                isAck[0] = fdbk->isAck[2];
3468             }
3469
3470             /* Not releasing pdcch here
3471              * as it is already done at the time of
3472              * reception req */
3473             rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3474          }
3475          else
3476 #endif
3477          {
3478             if (!sf->relPdcch)
3479             {
3480                RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId, 
3481                   "CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3482                   "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3483                   timingInfo.slot);
3484                return RFAILED;
3485             }
3486
3487             isAck[0] = fdbk->isAck[0];
3488             /* Note: Since relPdcchFbkTimimg matches with the recieved
3489              * feedback, assumed that feedback is for release PDCCH */
3490             rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3491
3492             /* Remove release PDCCH from the subframe */
3493             rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3494             sf->relPdcch = NULLP;
3495             return ROK;
3496          }
3497       }
3498    }
3499 #endif /* LTEMAC_SPS */
3500    
3501    /* Remove the harq process from the subframe */
3502    sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3503    RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3504    
3505 #ifdef CA_DBG
3506    {
3507       if(ue)
3508       {
3509          gHqFdbkCount++;
3510       }
3511    }
3512
3513 #endif   
3514    while (hqPCount)
3515    {
3516       if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3517       {
3518          hqP = (RgSchDlHqProcCb *)node->node;
3519          node = node->next;
3520          rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3521       }
3522       procId = hqP->procId;
3523
3524       rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3525
3526       /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3527        * On the basis of f1bCsAVal find the position of iAck or Nack*/
3528 #ifdef LTE_ADV
3529       if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3530       {
3531          rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack); 
3532       }
3533       else
3534 #endif
3535       {
3536          rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk); 
3537       }
3538       for (tbCnt = 0; tbCnt < 2; tbCnt++)
3539       {
3540          if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3541          {
3542             rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt, 
3543                   timingInfo, isAck[tbCnt], rlsHqBufs, err);
3544          }
3545       }
3546       if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3547       {
3548          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3549          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = 
3550             (U8)procId;
3551          rlsHqBufs->numUes++;
3552       }
3553       hqPCount--;
3554    }
3555
3556    node = sf->ackNakRepQ.first;
3557    while (node)
3558    {
3559       tbCb = (RgSchDlHqTbCb *)(node->node);
3560       hqP = tbCb->hqP;
3561
3562       procId = hqP->procId;
3563       rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3564       rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3565       if (HQ_TB_WAITING == tbCb->state)
3566       {
3567          isAck[0] = fdbk->isAck[tbCb->tbIdx];
3568          rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3569                timingInfo, isAck[0], rlsHqBufs, err);
3570       }
3571       hqP->cwSwpEnabled = FALSE;
3572       if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3573       {
3574          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3575          rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = 
3576             (U8)procId;
3577          rlsHqBufs->numUes++;
3578       }
3579       hqPCount--;
3580       node = node->next;
3581    }
3582
3583    return (ret);
3584 }  /* rgSCHDhmHqFdbkInd */
3585 #endif /* LTE_FDD */
3586
3587
3588 /**
3589  * @brief Handler for Harq related UE configuration.
3590  *
3591  * @details
3592  *
3593  *     Function : rgSCHDhmRgrUeCfg
3594  *     
3595  *     This function shall fetch the harq related information into the
3596  *     respective ueCb from the UE configuration as provided by the 
3597  *     upper layers. 
3598  *           
3599  *  @param[in]  RgSchCellCb   *cell 
3600  *  @param[in]  RgSchUeCb     *ueCb 
3601  *  @param[in]  RgrUeCfg      *ueCfg 
3602  *  @param[out] RgSchErrInfo     *err
3603  *  @return     S16
3604  *      -# ROK 
3605  *      -# RFAILED 
3606  **/
3607 #ifdef ANSI
3608 Void rgSCHDhmRgrUeCfg
3609 (
3610 RgSchCellCb       *cell,
3611 RgSchUeCb         *ueCb,
3612 RgrUeCfg          *ueCfg,
3613 RgSchErrInfo      *err
3614 )
3615 #else
3616 Void rgSCHDhmRgrUeCfg(cell, ueCb, ueCfg, err)
3617 RgSchCellCb       *cell;
3618 RgSchUeCb         *ueCb;
3619 RgrUeCfg          *ueCfg;
3620 RgSchErrInfo      *err;
3621 #endif
3622 {
3623
3624    UNUSED(err);
3625
3626    /* Initialize the TA Timer */
3627    cmInitTimers(&ueCb->taTmr, 1);
3628
3629    /* Setting these values irrespective of taTmr value */
3630    ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3631    /* Corrected default value of TA as per 36.213, 4.2.3 */
3632    ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3633   
3634    /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3635    ueCb->dl.taCb.outStndngTa = FALSE;
3636    ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3637    
3638    /* Start TA timer only if cfgd as FINITE value */
3639    if (ueCfg->ueTaTmrCfg.pres)
3640    {
3641       /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3642        * TA command before the expiry of TA at UE. Also considering for 
3643        * possible retx for this TA command */
3644       /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3645       if(ueCfg->ueTaTmrCfg.taTmr > 30)
3646       {
3647          ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30; 
3648       }
3649       rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3650    }
3651    RETVOID;
3652 }  /* rgSCHDhmRgrUeCfg */
3653
3654
3655 /**
3656  * @brief Handler for HARQ related UE Reconfiguration
3657  *
3658  * @details
3659  *
3660  *     Function : rgSCHDhmRgrCellCfg
3661  *     
3662  *     This function shall fetch the HARQ related information into the
3663  *     respective ueCb from the UE configuration as provided by the 
3664  *     upper layers. 
3665  *           
3666  *  @param[in]  RgSchCellCb     *cell 
3667  *  @param[in]  RgrCellCfg   *cellCfg
3668  *  @param[out] RgSchErrInfo    *err 
3669  *
3670  *  @return     S16
3671  *                -# ROK 
3672  *                -# RFAILED 
3673  **/
3674 #ifdef ANSI
3675 Void rgSCHDhmRgrCellCfg
3676 (
3677 RgSchCellCb    *cell,
3678 RgrCellCfg     *cellCfg,
3679 RgSchErrInfo   *err
3680 )
3681 #else
3682 Void rgSCHDhmRgrCellCfg(cell, cellCfg, err)
3683 RgSchCellCb    *cell;
3684 RgrCellCfg     *cellCfg;
3685 RgSchErrInfo   *err;
3686 #endif
3687 {
3688    RgSchDlHqEnt         *hqE;
3689    PTR         pUeCb;/* previous UE Control block */
3690    PTR         nUeCb;/* next UE control block */
3691    S16         ret;
3692    U8          idx;
3693
3694    UNUSED(err);
3695
3696    pUeCb = NULLP;
3697    
3698    cell->dlHqCfg = cellCfg->dlHqCfg;
3699    for (;;)
3700    {
3701       ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3702       if (ret != ROK)
3703       {
3704          break;
3705       }
3706       else
3707       {
3708          pUeCb = nUeCb;
3709          /* Update the DL Harq related information */
3710          hqE   = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3711          hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3712       }
3713    }
3714    /* Initializing the list for ueCbs that would have ta */
3715    cmLListInit(&cell->taUeLst);
3716 #ifdef RGR_V1
3717    cmLListInit(&cell->ccchSduUeLst);
3718    cmLListInit(&cell->contResGrdTmrLst);
3719    cmLListInit(&cell->contResTmrLst);
3720 #ifdef EMTC_ENABLE
3721    if(cell->emtcEnable)
3722    {
3723       rgSCHDhmEmtcRgrCellCfg(cell);
3724    }
3725 #endif
3726 #endif
3727
3728    /* Initializing the timer queue */
3729    cell->tqCp.nxtEnt = 0;
3730    cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3731
3732    for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3733    {
3734      cell->tq[idx].first = NULLP;
3735      cell->tq[idx].tail  = NULLP;
3736    }
3737    RETVOID;
3738 }  /* rgSCHDhmRgrCellCfg */
3739
3740 /**
3741  * @brief Handler for Updating HARQ Information from Cell Reconfiguration 
3742  *
3743  * @details
3744  *
3745  *     Function : rgSCHDhmRgrCellRecfg
3746  *     
3747  *     This function shall fetch the HARQ related information into the
3748  *     respective ueCb from the UE configuration as provided by the 
3749  *     upper layers. 
3750  *           
3751  *  @param[in]  RgSchCellCb     *cell 
3752  *  @param[in]  RgrCellRecfg *cellRecfg
3753  *  @param[out] RgSchErrInfo    *err 
3754  *
3755  *  @return     S16
3756  *                -# ROK 
3757  *                -# RFAILED 
3758  **/
3759 #ifdef ANSI
3760 Void rgSCHDhmRgrCellRecfg
3761 (
3762 RgSchCellCb    *cell,
3763 RgrCellRecfg   *cellRecfg,
3764 RgSchErrInfo   *err
3765 )
3766 #else
3767 Void rgSCHDhmRgrCellRecfg(cell, cellRecfg, err)
3768 RgSchCellCb    *cell;
3769 RgrCellRecfg   *cellRecfg;
3770 RgSchErrInfo   *err;
3771 #endif
3772 {
3773    RgSchDlHqEnt         *hqE;
3774    PTR         pUeCb;/* previous UE Control block */
3775    PTR         nUeCb;/* next UE control block */
3776    S16         ret;
3777
3778    UNUSED(err);
3779
3780    pUeCb = NULLP;
3781    
3782    /* Update the cell with recieved configuration */
3783    if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3784    {
3785       cell->dlHqCfg  =  cellRecfg->dlHqRecfg;
3786
3787       for (;;)
3788       {
3789          ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3790          if (ret != ROK)
3791          {
3792             break;
3793          }
3794          else
3795          {
3796             pUeCb = nUeCb;
3797             /* Update the DL Harq related information */
3798             hqE      = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3799             hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3800          }
3801       }
3802    }
3803    RETVOID;
3804 }  /* rgSCHDhmRgrCellRecfg */
3805
3806 /**
3807  * @brief Handler for freeing up the HARQ related information from ueCb
3808  *
3809  * @details
3810  *
3811  *     Function : rgSCHDhmFreeUe
3812  *     
3813  *     This function shall free up the HARQ specific information from ueCb.
3814  *           
3815  *  @param[in]  RgSchUeCb     *ueCb 
3816  *
3817  *  @return     None.
3818  *
3819  **/
3820 #ifdef ANSI
3821 Void rgSCHDhmFreeUe
3822 (
3823 RgSchUeCb          *ueCb
3824 )
3825 #else
3826 Void rgSCHDhmFreeUe(ueCb)
3827 RgSchUeCb          *ueCb;
3828 #endif
3829 {
3830
3831    /* If TA Timer is running. Stop it */
3832    if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3833    {
3834       rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3835    }
3836
3837    /* ccpu00118357 - ADD - stop the periodic BSR timer so it 
3838     * doesn't expire after UE is deleted */
3839 #ifdef RGR_V1
3840    if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3841    {
3842       rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3843    }
3844 #endif /* ifdef RGR_V1*/
3845
3846    
3847    if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3848    {
3849       rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3850    }
3851
3852    /* This UE needs to be removed from its entry into cell's taUeLst */
3853    /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3854    if(ueCb->taLnk.node)
3855    {
3856       cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3857       ueCb->taLnk.node = NULLP; 
3858    }
3859
3860    if (ueCb->dlTaLnk.node != NULLP)
3861    {
3862       /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3863        * function directly from other modules. APIs should be defined and/or used
3864        * instead. Please check for other possible incorrect usage. */      
3865       rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3866    }
3867
3868    RETVOID;
3869
3870 }  /* rgSCHDhmFreeUe */
3871
3872 /**
3873  * @brief Handler for updating the TA.
3874  *
3875  * @details
3876  *
3877  *     Function : rgSCHDhmUpdTa
3878  *     
3879  *     This function shall update the TA received. 
3880  *           
3881  *  @param[in]  RgSchCellCb   *cell 
3882  *  @param[in]  RgSchUeCb     *ueCb 
3883  *  @param[in]  U8         ta
3884  *
3885  *  @return     None.
3886  *
3887  **/
3888 #ifdef ANSI
3889 Void rgSCHDhmUpdTa
3890 (
3891 RgSchCellCb    *cell,
3892 RgSchUeCb      *ueCb,
3893 U8             ta
3894 )
3895 #else
3896 Void rgSCHDhmUpdTa(cell, ueCb, ta)
3897 RgSchCellCb    *cell;
3898 RgSchUeCb      *ueCb;
3899 U8             ta;
3900 #endif
3901 {
3902
3903    if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3904    {
3905       ueCb->dl.taCb.state     =  RGSCH_TA_TOBE_SCHEDULED;
3906       ueCb->dl.taCb.numRemSf  =  2;
3907       rgSCHUtlDlTARpt(cell, ueCb);  
3908       /* If TA Timer is running. Stop it */
3909       if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3910       {
3911          rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3912       }
3913           
3914           /* SR_RACH_STATS : TA MODIFIED */
3915       if (ueCb->dl.taCb.ta != ta)
3916       {
3917          rgNumTAModified++;
3918       }
3919       ueCb->dl.taCb.ta        =  ta;
3920    }
3921    else
3922    {
3923       /* [ccpu00121813]-ADD-Updating outstanding values 
3924       * TA which gets transmitted at N gets applied at UE at N+6,once TA
3925       * has been scheduled,further TA values get stored in outstndngTaval.
3926       * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3927       * then schedule the outstanding TA val if present */
3928       ueCb->dl.taCb.outStndngTa    =  TRUE;
3929       ueCb->dl.taCb.outStndngTaval =  ta;
3930    }
3931
3932    RETVOID;
3933 }  /* rgSCHDhmUpdTa */
3934
3935  /** @brief This function handles the TA timer expiry.
3936   *
3937   * @details
3938   *
3939   *     Function: This function handled the TA Expiry.
3940   *
3941   *         Processing steps:
3942   *         - 
3943   *
3944   *
3945   * @param[in] RgSchUeCb  *ueCb  
3946   *
3947   * @return Void
3948   *      -#None.
3949   */
3950 #ifdef ANSI
3951 Void rgSCHDhmProcTAExp 
3952 (
3953  RgSchUeCb  *ueCb
3954  )
3955 #else
3956 Void rgSCHDhmProcTAExp (ueCb)
3957  RgSchUeCb  *ueCb;
3958 #endif
3959 {
3960    /* Ask scheduler to schedule this UE */
3961    ueCb->dl.taCb.state     =  RGSCH_TA_TOBE_SCHEDULED;
3962    rgSCHUtlDlTARpt(ueCb->cell, ueCb);  
3963    RETVOID;
3964 } /* end of rgSCHDhmProcTAExp */ 
3965
3966 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
3967 /**
3968  * @brief Handler for Adding scheduled logical channel data information  
3969  *        to harqProc.
3970  *                    
3971  * @details
3972  *
3973  *     Function : rgSCHDhmAddLcData
3974  *     
3975  *     This function shall add the scheduled logical channel data 
3976  *     information to the HARQ process. 
3977  *           
3978  *  @param[in]  RgSchLchAllocInfo  *lchData
3979  *  @param[in]  RgSchDlHqTbCb     *tbInfo
3980  *  @return     S16
3981  *      -# ROK 
3982  *      -# RFAILED 
3983  **/
3984 #ifdef ANSI
3985 S16 rgSCHDhmAddLcData
3986 (
3987 Inst               inst,
3988 RgSchLchAllocInfo  *lchData,
3989 RgSchDlHqTbCb      *tbInfo
3990 )
3991 #else
3992 S16 rgSCHDhmAddLcData(inst, lchData, tbInfo)
3993 Inst               inst;
3994 RgSchLchAllocInfo  *lchData;
3995 RgSchDlHqTbCb      *tbInfo;
3996 #endif
3997 {
3998
3999    if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
4000    {
4001      return RFAILED;
4002    } 
4003
4004    tbInfo->lchSchdDataArr[tbInfo->numLch]   = *lchData;
4005
4006    tbInfo->numLch++;
4007
4008    return ROK;
4009
4010 }  /* rgSCHDhmAddLcData */
4011
4012 #ifdef LTE_TDD
4013 /*
4014  * @brief Handler for releaseing the subframe allocation.
4015  *
4016  * @details
4017  *
4018  *     Function : rgSCHDhmTddRlsSubFrm
4019  *
4020  *     This function shall be invoked to release the DL Sf 
4021  *     allocations for which HARQ feedback time has expired.
4022  *
4023  *  @param[in]  RgSchCellCb      *cellCb
4024  *  @param[in]  CmLteTimingInfo  uciTimingInfo;
4025  *  @return     S16
4026  *      -# ROK
4027  *      -# RFAILED
4028  **/
4029 #ifdef ANSI
4030 S16 rgSCHDhmTddRlsSubFrm
4031 (
4032 RgSchCellCb          *cellCb,
4033 CmLteTimingInfo      uciTimingInfo
4034 )
4035 #else
4036 S16 rgSCHDhmTddRlsSubFrm(cellCb, uciTimingInfo)
4037 RgSchCellCb          *cellCb;
4038 CmLteTimingInfo      uciTimingInfo;
4039 #endif
4040 {
4041    CmLteTimingInfo         dlSfTime;
4042    RgSchTddDlAscSetIdxK    ascIdx;
4043    U8                      noFdbks;
4044    U8                      i;
4045
4046    ascIdx = 
4047       rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4048    noFdbks = ascIdx.numFdbkSubfrms;
4049    for(i=0; i < noFdbks; i++)
4050    {
4051       /* Get the subframe and sfn for which HARQ Ack/Nack
4052        * has to be sent */
4053       /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4054       /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper 
4055        * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() 
4056        * as it is serving the purpose */
4057       RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4058       rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
4059    }
4060    return ROK;
4061 }/* rgSCHDhmTddRlsSubFrm */
4062
4063 #ifdef TFU_TDD
4064 U32 macDtx = 0;
4065 #endif
4066 /**
4067  * @brief Handler for Removing the HARQ process from a dlsf.
4068  *
4069  * @details
4070  *
4071  *     Function : rgSCHDhmRlsDlsfHqProc
4072  *
4073  *     This function shall be invoked for every tti. It goes back to
4074  *     to the sixth last subframe to check whether it still exists. If
4075  *     that exists this function traverses through the entire harq
4076  *     proc list associated and frees up all of them.
4077  *
4078  *  @param[in]  RgSchCellCb      *cellCb
4079  *  @param[in]  CmLteTimingInfo  timingInfo
4080  *  @return     S16
4081  *      -# ROK
4082  *      -# RFAILED
4083  **/
4084 #ifdef ANSI
4085 S16 rgSCHDhmRlsDlsfHqProc
4086 (
4087 RgSchCellCb          *cellCb,
4088 CmLteTimingInfo      uciTimingInfo
4089 )
4090 #else
4091 S16 rgSCHDhmRlsDlsfHqProc(cellCb, uciTimingInfo)
4092 RgSchCellCb          *cellCb;
4093 CmLteTimingInfo      uciTimingInfo;
4094 #endif
4095 {
4096    RgSchDlSf               *dlSf;
4097    CmLteTimingInfo         dlSfTime;
4098    CmLteTimingInfo         nxtfrm = {0,0};
4099    RgSchDlHqProcCb         *tmpHqProc;
4100    RgSchTddDlAscSetIdxK    ascIdx;
4101    U8                      noFdbks;
4102    S16                     i;
4103    RgSchDlSf               *nxtDlsf = NULLP;
4104    CmLList                 *node;
4105    CmLList                 *hqPNode;
4106    U8                      idx;
4107    /*ccpu00130018 -MOD -Initiatizing with FALSE*/ 
4108    U8                      maxRetx=FALSE;
4109    RgSchTddANInfo          *anInfo = NULLP;
4110    RgSchDlHqTbCb           *tbCb;
4111    RgSchUeCb               *ue = NULLP;
4112
4113    ascIdx = 
4114       rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4115    noFdbks = ascIdx.numFdbkSubfrms;
4116    for(i=0; i < noFdbks; i++)
4117    {
4118       /* Get the subframe and sfn for which HARQ Ack/Nack
4119        * has to be sent */
4120       /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4121       /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper 
4122        * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() 
4123        * as it is serving the purpose */
4124       RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4125
4126       dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
4127       if(cellCb->ulDlCfgIdx != 5)
4128       {
4129          rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
4130       }
4131       /* Subframe is present. Delete all the harq associations from 
4132        * this subframe.
4133        */
4134
4135       /*Handling for Msg4*/
4136       node = dlSf->msg4HqPLst.first;
4137       while (node)
4138       {
4139          tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4140          node = node->next;
4141          tmpHqProc->cwSwpEnabled = FALSE;
4142          if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4143          {
4144             tbCb = &tmpHqProc->tbInfo[0];
4145
4146             /* Fix : syed MultiUe per TTI crash in TA List. */
4147             maxRetx = FALSE;
4148
4149             tbCb->dtxCount++;
4150             tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4151
4152
4153             rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4154
4155             /* Delete the Harq Association. Release the Harq Process */
4156             rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4157
4158             if (tbCb->taSnt == TRUE)
4159             {
4160                /* [ccpu00127148] Correcting the check */
4161                if (TRUE == maxRetx)
4162                {
4163                   tbCb->taSnt                  =  FALSE;
4164                   RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4165                      ue->dl.taCb.state = RGSCH_TA_IDLE;
4166
4167                   rgSCHUtlReTxTa(cellCb, ue);
4168                }
4169             }
4170          }
4171       } 
4172
4173       node = dlSf->ueLst.first;
4174       while (node)
4175       {
4176 #ifdef TFU_TDD
4177          macDtx++;
4178 #endif
4179          ue = (RgSchUeCb *)(node->node);
4180          node = node->next;
4181          if (NULLP != ue)
4182          {
4183             hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
4184             while (hqPNode)
4185             {
4186                tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4187                hqPNode = hqPNode->next;
4188                for (idx = 0 ;idx < 2; idx++)
4189                {
4190                   if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4191                   {
4192                      tbCb = &tmpHqProc->tbInfo[idx];
4193
4194                      /* Fix : syed MultiUe per TTI crash in TA List. */
4195                      maxRetx = FALSE;
4196
4197                      tbCb->dtxCount++;
4198                      tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4199
4200
4201                      /* Update feedback time for this process so that 
4202                       * next subframe its picked up */
4203 #ifdef LTE_ADV
4204                      U8 servCellIdx = rgSchUtlGetServCellIdx(
4205                            tmpHqProc->hqE->cell->instIdx,
4206                            tmpHqProc->hqE->cell->cellId,
4207                            ue);
4208                      anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4209 #else
4210                      anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
4211 #endif
4212                      if(anInfo == NULLP)
4213                      {
4214                         RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx), 
4215                                  "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX" 
4216                                  "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn, 
4217                                  uciTimingInfo.slot));
4218                      }
4219                      else  if (tbCb->fbkRepCntr == 0)
4220                      {
4221                         /* Initialise the Ack/Nack feedback */
4222                         anInfo->dlDai--;
4223                         if(!(anInfo->dlDai))
4224                         {
4225                            rgSCHUtlInitUeANFdbkInfo(anInfo);
4226                         }
4227                      }
4228                      else
4229                      {
4230                         /* Update feedback time for this process so that
4231                          *              * next subframe its picked up */
4232                         RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf); 
4233                         RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4234                         RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4235                         rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
4236                         tbCb->fbkRepCntr--;
4237                         continue;
4238
4239                      }
4240                      rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4241                      /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
4242
4243                      {
4244                         /* Delete the Harq Association. Release the Harq Process */
4245                         rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4246                      }
4247                      if (tbCb->taSnt == TRUE)
4248                      {
4249                         /* [ccpu00127148] Correcting the check */
4250                         if (TRUE == maxRetx)
4251                         {
4252                            tbCb->taSnt                  =  FALSE;
4253                            RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4254                               ue->dl.taCb.state = RGSCH_TA_IDLE;
4255
4256                            rgSCHUtlReTxTa(cellCb, ue);
4257
4258                            RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4259                                    "Nack/DTX Rcvd for TA. Max Tries Attempted");
4260                         }
4261                      }
4262                   }
4263                }
4264             }
4265          }
4266       }
4267
4268       node = dlSf->ackNakRepQ.first;
4269       while (node)
4270       {
4271          tbCb = (RgSchDlHqTbCb *)(node->node);
4272          tmpHqProc = tbCb->hqP;
4273          /* [ccpu00121813]-ADD-Fetch ueCb */
4274          ue = tmpHqProc->hqE->ue;
4275          /* Fix : syed MultiUe per TTI crash in TA List. */
4276          maxRetx = FALSE;
4277          
4278          tbCb->dtxCount++;
4279 #ifdef TENB_STATS
4280          tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
4281          ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
4282 #endif
4283
4284          node = node->next;
4285          /* If This is not the last repetition */
4286          if (tbCb->fbkRepCntr > 1)
4287          {
4288             /* Update feedback time for this process so that 
4289              * next subframe its picked up */
4290 #ifdef LTE_ADV
4291             U8 servCellIdx = rgSchUtlGetServCellIdx(
4292                   tmpHqProc->hqE->cell->instIdx,
4293                   tmpHqProc->hqE->cell->cellId,
4294                   ue);
4295             anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4296 #else
4297             anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
4298 #endif
4299             if(anInfo == NULLP)
4300             {
4301                return RFAILED;
4302             }
4303             RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4304             RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4305             RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4306             rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4307             tbCb->fbkRepCntr--;
4308             continue;
4309          }
4310          else
4311          {
4312             rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4313
4314             if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
4315             {
4316                /*even if one NACK, we consider the feedback
4317                 * on a whole as NACk */
4318                if ( tbCb->nackCount != 0 )
4319                {
4320                   tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4321                }
4322                else
4323                {
4324                   tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4325                }
4326               
4327             {
4328                /* Delete the Harq Association. Release the Harq Process */
4329               rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4330             }
4331            }/*if(((tbCb->nackCount+....*/
4332          }/*else....*/
4333
4334          if (tbCb->taSnt == TRUE)
4335          {
4336             /* [ccpu00127148] Correcting the check */
4337             if (TRUE == maxRetx)
4338             {
4339                tbCb->taSnt                  =  FALSE;
4340                ue->dl.taCb.state = RGSCH_TA_IDLE;
4341                
4342                rgSCHUtlReTxTa(cellCb, ue); 
4343                RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4344                      "Nack/DTX Rcvd for TA. Max Tries Attempted");
4345                
4346              }
4347          }
4348       }
4349    }
4350    return ROK;
4351 }/* rgSCHDhmRlsDlsfHqProc */
4352 #else /* ifdef LTE_TDD */
4353 /**
4354  * @brief Handler for Removing the HARQ process from a dlsf.
4355  *                    
4356  * @details
4357  *
4358  *     Function : rgSCHDhmRlsDlsfHqProc
4359  *     
4360  *     This function shall be invoked for every tti. It goes back to
4361  *     to the sixth last subframe to check whether it still exists. If
4362  *     that exists this function traverses through the entire harq 
4363  *     proc list associated and frees up all of them.  
4364  *           
4365  *  @param[in]  RgSchCellCb     *cell 
4366  *  @return     S16
4367  *      -# ROK 
4368  *      -# RFAILED 
4369  **/
4370 #ifdef ANSI
4371 S16 rgSCHDhmRlsDlsfHqProc
4372 (
4373 RgSchCellCb          *cell,
4374 CmLteTimingInfo      timingInfo
4375 )
4376 #else
4377 S16 rgSCHDhmRlsDlsfHqProc(cell, timingInfo)
4378 RgSchCellCb          *cell;
4379 CmLteTimingInfo      timingInfo;
4380 #endif
4381 {
4382    RgSchDlSf         *sf;
4383    CmLteTimingInfo   frm;
4384    RgSchDlHqProcCb   *tmpHqProc;
4385    Bool              maxRetx;
4386    CmLList           *node;
4387    CmLList           *hqPNode;
4388    U8                idx;
4389    RgSchDlHqTbCb     *tbCb;
4390    RgSchUeCb         *ue;
4391
4392    /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
4393    /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper 
4394     * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() 
4395     * as it is serving the purpose */
4396    RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL); 
4397    
4398
4399    /* Get the required Last subframe */
4400    sf = rgSCHUtlSubFrmGet(cell, frm);
4401
4402    /*CA Dev Start*/
4403    /*Handling for Msg4*/
4404    node = sf->msg4HqPLst.first;
4405    while (node)
4406    {
4407       tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4408       if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4409       {
4410          tbCb = &tmpHqProc->tbInfo[0];
4411          /* Fix : syed MultiUe per TTI crash in TA List. */
4412          maxRetx = FALSE;
4413
4414          RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4415                   txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4416
4417          tbCb->dtxCount++;
4418          if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) || 
4419                (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4420          {
4421             tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4422             rgNumMsg4Dtx++;
4423          }
4424
4425          node = node->next;
4426          if (tbCb->fbkRepCntr != 0)
4427          {
4428             /* Update timingInfo for this hqP so that next subframe its picked up */
4429             RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4430             rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4431             tbCb->fbkRepCntr--;
4432             continue;
4433          }
4434          rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4435
4436          /* Delete the Harq Association. Release the Harq Process */
4437          rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4438
4439       }
4440    } 
4441    /* Subframe is present. Delete all the harq associations from 
4442     * this subframe.
4443     */
4444    node = sf->ueLst.first;
4445    while (node)
4446    {
4447       ue = (RgSchUeCb *)(node->node);
4448       node = node->next;
4449       if(ue != NULLP)
4450       {
4451          hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4452
4453          while (hqPNode)
4454          {
4455             tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4456             tmpHqProc->cwSwpEnabled = FALSE;
4457             hqPNode = hqPNode->next;
4458             for (idx = 0 ;idx < 2; idx++)
4459             {
4460                if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4461                {
4462                   tbCb = &tmpHqProc->tbInfo[idx];
4463                   /* Fix : syed MultiUe per TTI crash in TA List. */
4464                   maxRetx = FALSE;
4465
4466                   RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4467                            txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4468
4469                   tbCb->dtxCount++;
4470                   if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) || 
4471                         (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4472                   {
4473                      tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4474                      rgNumMsg4Dtx++;
4475                   }
4476                   else
4477                   {
4478                      tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4479                   }
4480
4481                   rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4482
4483                   {
4484                      /* Delete the Harq Association. Release the Harq Process */
4485                      rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4486                   }
4487                   if (tbCb->taSnt == TRUE)
4488                   {
4489                      /* [ccpu00127148] Correcting the check */
4490                      if (TRUE == maxRetx)
4491                      {
4492                         tbCb->taSnt                  =  FALSE;
4493                         ue->dl.taCb.state = RGSCH_TA_IDLE;
4494
4495                         rgSCHUtlReTxTa(cell, ue); 
4496                         RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx), 
4497                                  "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4498                      }
4499                   }
4500                   RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4501                   ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4502                }
4503             }
4504          }
4505       }
4506    }
4507    /*CA Dev End*/
4508
4509    return ROK;
4510 }  /* rgSCHDhmRlsDlsfHqProc */
4511 #endif
4512 #ifdef LTEMAC_SPS
4513 #ifdef RG_UNUSED
4514 /**
4515  * @brief This function marks the HARQ process with a given ID as SPS HARQ
4516  * proc
4517  *
4518  * @details
4519  *
4520  *     Function: rgSCHDhmMarkSpsHqProc
4521  *     Purpose:  This function returns the HARQ process with the given ID.
4522  *     Invoked by: SPS Module
4523  *     Processing steps: 
4524  *     - Get the HARQ process by index from the UE
4525  *     - Set isSpsHqProc = TRUE
4526  *     
4527  *  @param[in]  RgSchUeCb        *ue
4528  *  @param[in]  U8            idx
4529  *  @return  S16       
4530  *         -#   ROK     if successful
4531  *         -#   RFAILED otherwise
4532  *
4533  **/
4534 #ifdef ANSI
4535 S16 rgSCHDhmMarkSpsHqProc
4536 (
4537 RgSchUeCb               *ue,
4538 U8                      idx
4539 )
4540 #else
4541 S16 rgSCHDhmMarkSpsHqProc(ue, idx)
4542 RgSchUeCb               *ue;
4543 U8                      idx;
4544 #endif
4545 {
4546    RgSchDlHqProcCb      *hqP;
4547
4548    /* Pick the proc based on the index provided */
4549    rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4550
4551    return ROK;
4552 } /* rgSCHDhmMarkSpsHqProc */
4553 #endif /* RG_UNUSED */
4554 #endif /* LTEMAC_SPS */
4555
4556 #ifndef LTE_TDD
4557 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4558  *
4559  * @details
4560  *
4561  *     Function : rgSCHDhmProcHqFdbkAckNackRep
4562  *     
4563  *     This function shall act on the feedback received from TOM for DL
4564  *     transmission. 
4565  *     
4566  *           
4567  *  @param[in]  RgSchDlHqProcCb     *hqP
4568  *  @param[in]  RgSchDlSf           *sf                  
4569  *  @param[in]  U8                  tbCnt
4570  *  @param[in]  U8                  *isAck
4571  *  @return     S16
4572  *      -# ROK 
4573  *      -# RFAILED 
4574  **/
4575 #ifdef ANSI
4576 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep
4577 (
4578 RgSchDlHqProcCb      *hqP,
4579 RgSchDlSf            *sf,
4580 U8                   tbCnt,
4581 U8                   *isAck
4582 )
4583 #else
4584 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,isAck)
4585 RgSchDlHqProcCb      *hqP;
4586 RgSchDlSf            *sf;
4587 U8                   tbCnt;
4588 U8                   *isAck;
4589 #endif
4590 {
4591       /* Check if this is repeating UE */
4592     rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4593     /* Check if last repetition */
4594     if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4595     {
4596         /* Update timingInfo for this hqP so that next subframe its picked up */
4597         RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4598                                hqP->tbInfo[tbCnt].timingInfo, 1);
4599         return RFAILED;
4600     }
4601     
4602     /* Take decision here based on the number
4603      * of DTX's,NACK's and ACK's received
4604      */
4605     if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) + 
4606                 (hqP->tbInfo[tbCnt].dtxCount)))
4607     {
4608         *isAck = TFU_HQFDB_ACK; 
4609     }
4610     /*even a single NACK indicates that UE received
4611      * the transmission. 
4612      */
4613     else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4614     {
4615         *isAck = TFU_HQFDB_NACK;
4616     }
4617     else
4618     {
4619         *isAck = TFU_HQFDB_DTX;
4620     }
4621       
4622        
4623     hqP->tbInfo[tbCnt].isAckNackDtx = *isAck; 
4624     return ROK;
4625 }
4626 #endif /* ifndef LTE_TDD */
4627
4628
4629 /* Freeing up the HARQ proc blocked for
4630  * indefinite time in case of Retx */
4631 /**
4632  * @brief This function handles the scenario in case Retx allocation is failed.
4633  *
4634  * @details
4635  *
4636  *     Function: rgSCHDhmDlRetxAllocFail
4637  *     Purpose:  
4638  *                
4639  *  @param[in]  RgSchUeCb             *ue
4640  *  @param[in]  RgSchDlHqProcCb       *hqP
4641  *  @return  Void 
4642  *
4643  **/
4644 #ifdef ANSI
4645 S16 rgSCHDhmDlRetxAllocFail 
4646 (
4647 RgSchUeCb               *ue,
4648 RgSchDlHqProcCb         *hqP
4649 )
4650 #else
4651 S16 rgSCHDhmDlRetxAllocFail(ue, hqP)
4652 RgSchUeCb               *ue;
4653 RgSchDlHqProcCb         *hqP;
4654 #endif
4655 {
4656    RgSchCellCb      *cell;
4657    RgInfRlsHqInfo   *rlsHqInfo;
4658    Pst              pst;   
4659    Bool             maxRetx = FALSE;
4660    RgSchCmnCell           *cellSch;
4661
4662    cell = hqP->hqE->cell;
4663    cellSch = RG_SCH_CMN_GET_CELL(cell);
4664    rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4665  
4666    /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4667    if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4668    {
4669       hqP->tbInfo[0].cntrRetxAllocFail++;
4670    }
4671
4672    /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4673    if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4674    {
4675       hqP->tbInfo[1].cntrRetxAllocFail++;
4676    }
4677
4678    /* initialize MAC-SCH interface HARQ release info */
4679    rlsHqInfo->numUes = 0;
4680    rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4681
4682    /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4683    if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4684    {
4685       if (hqP->hqE->msg4Proc == hqP)
4686       {
4687          hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4688       }
4689       else
4690       {
4691          hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4692       }
4693
4694       rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4695
4696 #ifdef LTE_L2_MEAS
4697       if (maxRetx)
4698       {
4699       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4700                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4701       }
4702       else
4703       {
4704       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4705                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4706       }
4707 #else
4708       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4709                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4710 #endif
4711
4712       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4713                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4714       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4715    }
4716
4717    /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4718    if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4719    {
4720       if (hqP->hqE->msg4Proc == hqP)
4721       {
4722          hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4723       }
4724       else
4725       {
4726          hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4727       }
4728
4729       rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4730
4731       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4732                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4733       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4734                rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4735       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4736    }
4737
4738    /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4739    
4740    if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4741        (hqP->tbInfo[1].state != HQ_TB_NACKED))    
4742    {
4743       cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4744    }
4745
4746    /* send HARQ release to MAC */
4747    if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4748    {
4749       /* Fix : syed HO UE does not have a valid ue->rntiLnk */     
4750       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4751       rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4752       rlsHqInfo->numUes = 1;
4753
4754       rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4755       RgSchMacRlsHq(&pst, rlsHqInfo);
4756    }
4757
4758    return ROK;
4759 }
4760
4761 #ifdef DL_LA
4762 #ifdef ANSI
4763 PRIVATE S16 rgSCHDhmUpdateAckNackHistory
4764 (
4765 RgSchCellCb             *cell,
4766 RgSchUeCb               *ueCb,
4767 U8                      hqfdbk,
4768 U8                      tbCnt
4769 )
4770 #else
4771 PRIVATE S16 rgSCHDhmUpdateAckNackHistory(cell, ueCb, hqfdbk, tbCnt)
4772 (
4773 RgSchCellCb             *cell;
4774 RgSchUeCb               *ueCb;
4775 U8                      hqfdbk;
4776 U8                      tbCnt;
4777 )
4778 #endif
4779 {
4780    RgSchCmnDlUe  *ueDl;
4781    
4782    ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4783    
4784    /*
4785     * If fdbk is ack update totalNoOfAck and ackNackHistory for 
4786     * current idx
4787     */ 
4788    if (hqfdbk == TFU_HQFDB_ACK)
4789    {
4790       ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP; 
4791    }
4792    else   
4793    {         
4794       ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN; 
4795    }
4796    /*
4797    printf("deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n", 
4798            ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs, 
4799            (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4800            tbCnt);
4801    */
4802    rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt); 
4803
4804    return ROK;
4805 }
4806
4807 #ifdef ANSI
4808 S16 rgSCHDhmUpdBlerBasediTbsEff
4809 (
4810 RgSchCellCb             *cell,
4811 RgSchUeCb               *ueCb,
4812 U8                      tbCnt
4813 )
4814 #else
4815 S16 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt)
4816 (
4817 RgSchCellCb             *cell;
4818 RgSchUeCb               *ueCb;
4819 U8                      tbCnt;
4820 )
4821 #endif
4822 {
4823    S32            iTbs;
4824    RgSchCmnDlUe  *ueDl;
4825    RgSchCmnCell  *cellSch = RG_SCH_CMN_GET_CELL(cell);
4826    U8             cfi = cellSch->dl.currCfi;
4827    U8             maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4828    maxiTbs                = RG_SCH_DL_MAX_ITBS;
4829
4830    ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4831    iTbs =  (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100; 
4832  
4833    if (iTbs > maxiTbs)
4834    {
4835       ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4836       ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs); 
4837    }
4838    else if (iTbs < 0)
4839    {
4840       ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4841       ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0; 
4842    }
4843    else
4844    {
4845       ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4846                                                          ueDl->laCb[tbCnt].deltaiTbs)/100),  
4847                                                        ueCb->cell->thresholds.maxDlItbs);
4848    }
4849 #ifdef RG_5GTF
4850    ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4851 #endif
4852    ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4853
4854    /* Eff for CW for 1 Layer Tx */
4855    ueDl->mimoInfo.cwInfo[tbCnt].eff[0] = 
4856       (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4857       [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4858
4859    /* Eff for CW for 2 Layer Tx */
4860    ueDl->mimoInfo.cwInfo[tbCnt].eff[1] = 
4861       (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4862       [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4863
4864    return ROK;
4865 }
4866 #endif
4867
4868 #ifdef LTE_TDD
4869 /**
4870  * @brief This function Processes the Hq Fdbk in case of 
4871  *        special Bundling in TDD (FAPIv1.1: Table 79)   
4872  *
4873  * @details
4874  *
4875  *     Function: rgSCHDhmPrcSplBundlFdbk
4876  *     Purpose: To Interpret the Harq Feedback according to
4877  *              table 7.3-1: 36.213
4878  *    
4879  *          0 = 0 or None (UE detect at least one DL is missed)
4880  *          1 = 1 or 4 or 7 ACKs reported
4881  *          2 = 2 or 5 or 8 ACKs reported
4882  *          3 = 3 or 6 or 9 ACKs reported
4883  *          4 = DTX (UE did not transmit anything)
4884  *                
4885  *  @param[in]  TfuHqInfo    *fdbk
4886  *  @param[in]  U8            hqCnt 
4887  *  @return  Void 
4888  *
4889  **/
4890 #ifdef ANSI
4891 PRIVATE Void rgSCHDhmPrcSplBundlFdbk
4892 (
4893 RgSchCellCb  *cell,
4894 TfuHqInfo    *fdbk,
4895 U8            hqCnt
4896 )
4897 #else
4898 PRIVATE Void rgSCHDhmPrcSplBundlFdbk(cell, fdbk, hqCnt)
4899 (
4900 RgSchCellCb  *cell;
4901 TfuHqInfo    *fdbk;
4902 U8            hqCnt;
4903 )
4904 #endif
4905 {
4906    U8       numOfAcks;
4907    
4908    /* Num of ACKs reported by UE */
4909    numOfAcks = fdbk->isAck[0];
4910
4911    if(fdbk->isAck[0] == TFU_HQFDB_NACK || 
4912       fdbk->isAck[0] == TFU_HQFDB_DTX)
4913    {
4914       /* NACK/DTX CASE */
4915    } 
4916    else 
4917    {
4918       RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, 
4919             rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4920
4921       fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4922                                                  [(numOfAcks-1)];  
4923    }
4924    /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4925       the PDSCH trasnmission (spatial bundling). So we have 
4926       to assume same feedback for both codewords */ 
4927 #ifdef LTE_ADV
4928    for(U8 idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4929    {
4930       fdbk->isAck[idx] = fdbk->isAck[0]; 
4931    }
4932 #else
4933    fdbk->isAck[1] = fdbk->isAck[0]; 
4934 #endif
4935    
4936    RETVOID;
4937 }
4938 #endif
4939
4940 /**
4941  * @brief This function adds HARQ process to FREE list
4942  *
4943  * @details
4944  *
4945  *     Function: rgSCHDhmHqPAdd2FreeLst
4946  *     Purpose:  
4947  *     
4948  *     Invoked by: scheduler
4949  *     
4950  *  @param[out] RgDlHqProc       *hqP
4951  *  @return  Void      
4952  *
4953  **/
4954 #ifdef ANSI
4955 Void rgSCHDhmHqPAdd2FreeLst
4956 (
4957 RgSchDlHqProcCb         *hqP
4958 )
4959 #else
4960 Void rgSCHDhmHqPAdd2FreeLst(hqP)
4961 RgSchDlHqProcCb         *hqP;
4962 #endif
4963 {
4964
4965 #ifdef LAA_DBG
4966    if (hqP->hqPLst)
4967    {
4968       int *p = NULL;
4969       printf("Crashing already part of free lst\n");
4970       printf("Crashing %d \n", *p);
4971       *p = 10;
4972    }
4973 #endif
4974    cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
4975    hqP->hqPLst = &hqP->hqE->free;
4976
4977
4978 #ifdef LAA_DBG
4979    if (hqP->hqE->free.count > 8)
4980    {
4981       int *p = NULL;
4982       printf("Crashing invalid hq count\n");
4983       printf("Crashing %d \n", *p);
4984       *p = 10;
4985    }
4986 #endif
4987
4988 #ifdef LTE_ADV
4989    rgSCHLaaHndlHqProcFree(hqP);
4990 #endif
4991
4992    RETVOID;
4993 } /* rgSCHDhmHqPAdd2FreeLst */
4994
4995
4996 /**
4997  * @brief This function adds HARQ process to inUse list
4998  *
4999  * @details
5000  *
5001  *     Function: rgSCHDhmHqPAdd2InUseLst
5002  *     Purpose:  
5003  *     
5004  *     Invoked by: scheduler
5005  *     
5006  *  @param[out] RgDlHqProc       *hqP
5007  *  @return  Void      
5008  *
5009  **/
5010 #ifdef ANSI
5011 Void rgSCHDhmHqPAdd2InUseLst
5012 (
5013 RgSchDlHqProcCb         *hqP
5014 )
5015 #else
5016 Void rgSCHDhmHqPAdd2InUseLst(hqP)
5017 RgSchDlHqProcCb         *hqP;
5018 #endif
5019 {
5020
5021 #ifdef LAA_DBG
5022    if (hqP->hqPLst)
5023    {
5024       int *p = NULL;
5025       printf("Crashing already part of inuse lst\n");
5026       printf("Crashing %d \n", *p);
5027       *p = 10;
5028    }
5029 #endif
5030    cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
5031    hqP->hqPLst = &hqP->hqE->inUse;
5032
5033
5034 #ifdef LAA_DBG
5035    if (hqP->hqE->inUse.count > 8)
5036    {
5037       int *p = NULL;
5038       printf("Crashing invalid hq count \n");
5039       printf("Crashing %d \n", *p);
5040       *p = 10;
5041    }
5042 #endif
5043
5044    RETVOID;
5045 } /* rgSCHDhmHqPAdd2InUseLst */
5046
5047 /**
5048  * @brief This function adds HARQ process to FREE list
5049  *
5050  * @details
5051  *
5052  *     Function: rgSCHDhmHqPDelFrmFreeLst
5053  *     Purpose:  
5054  *     
5055  *     Invoked by: scheduler
5056  *     
5057  *  @param[out] RgDlHqProc       *hqP
5058  *  @return  Void      
5059  *
5060  **/
5061 #ifdef ANSI
5062 Void rgSCHDhmHqPDelFrmFreeLst
5063 (
5064 RgSchDlHqProcCb         *hqP
5065 )
5066 #else
5067 Void rgSCHDhmHqPDelFrmFreeLst(hqP)
5068 RgSchDlHqProcCb         *hqP;
5069 #endif
5070 {
5071
5072 #ifdef LAA_DBG
5073    if (!hqP->hqPLst)
5074    {
5075       int *p = NULL;
5076       printf("Crashing not part of any lst\n");
5077       printf("Crashing %d \n", *p);
5078       *p = 10;
5079    }
5080 #endif
5081 #ifdef LAA_DBG
5082    if (hqP->hqPLst != &hqP->hqE->free)
5083    {
5084       int *p = NULL;
5085       printf("Crashing del from wrong lst\n");
5086       printf("Crashing %d \n", *p);
5087       *p = 10;
5088    }
5089 #endif
5090
5091    cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
5092    hqP->hqPLst = NULLP;
5093
5094 #ifdef LAA_DBG
5095    if (hqP->hqE->free.count > 8)
5096    {
5097       int *p = NULL;
5098       printf("Crashing invalid hq count\n");
5099       printf("Crashing %d \n", *p);
5100       *p = 10;
5101    }
5102 #endif
5103
5104    RETVOID;
5105 } /* rgSCHDhmHqPDelFrmFreeLst */
5106
5107
5108
5109 /**
5110  * @brief This function adds HARQ process to FREE list
5111  *
5112  * @details
5113  *
5114  *     Function: rgSCHDhmHqPDelFrmInUseLst
5115  *     Purpose:  
5116  *     
5117  *     Invoked by: scheduler
5118  *     
5119  *  @param[out] RgDlHqProc       *hqP
5120  *  @return  Void      
5121  *
5122  **/
5123 #ifdef ANSI
5124 Void rgSCHDhmHqPDelFrmInUseLst
5125 (
5126 RgSchDlHqProcCb         *hqP
5127 )
5128 #else
5129 Void rgSCHDhmHqPDelFrmInUseLst(hqP)
5130 RgSchDlHqProcCb         *hqP;
5131 #endif
5132 {
5133
5134 #ifdef LAA_DBG
5135    if (!hqP->hqPLst)
5136    {
5137       int *p = NULL;
5138       printf("Crashing not part of any lst\n");
5139       printf("Crashing %d \n", *p);
5140       *p = 10;
5141
5142    }
5143 #endif
5144 #ifdef LAA_DBG
5145    if (hqP->hqPLst != &hqP->hqE->inUse)
5146    {
5147       int *p = NULL;
5148       printf("Crashing del from wrong lst\n");
5149       printf("Crashing %d \n", *p);
5150       *p = 10;
5151    }
5152 #endif
5153
5154    cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
5155    hqP->hqPLst = NULLP;
5156
5157 #ifdef LAA_DBG
5158    if (hqP->hqE->inUse.count > 8)
5159    {
5160       int *p = NULL;
5161       printf("Crashing invalid hq count\n");
5162       printf("Crashing %d \n", *p);
5163       *p = 10;
5164    }
5165 #endif
5166
5167    RETVOID;
5168 } /* rgSCHDhmHqPDelFrmInUseLst */
5169
5170 \f
5171 /**********************************************************************
5172  
5173          End of file
5174 **********************************************************************/