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