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