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