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