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