1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions
29 **********************************************************************/
31 /** @file rg_sch_dhm.c
32 @brief APIs related to Downlink HARQ for the scheduler.
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_FILE_ID=242;
37 static int RLOG_MODULE_ID=4096;
39 /* header include files -- defines (.h) */
40 #include "common_def.h"
46 #include "rg_sch_err.h"
47 #include "rg_sch_inf.h" /* typedefs for Scheduler */
49 #include "rg_sch_cmn.h"
50 #include "rl_interface.h"
51 #include "rl_common.h"
53 /* header/extern include files (.x) */
58 #include "rg_sch_inf.x" /* typedefs for Scheduler */
60 #include "rg_sch_cmn.x"
62 #ifdef RGSCH_SPS_STATS
63 uint32_t rgNumSPSSchedDropMaxRetx;
71 RgSchNackAckStats hqFailStats;
72 RgSchHqRetxStats hqRetxStats;
73 #endif /* MAC_SCH_STATS */
74 //Chandan Stats Collection
77 RgSchDlHqStats dlHqStats[10000] = {{0,0,0}};
81 /* For special bundling case: convert numOfAcks to ACK/NACK
82 * The below table derives the HARQ aknowledgement as ACK or NACK using the
83 * number of transmission done and the feedback value received
84 * The below table is based on Table 7.3-X from 36.213 and
85 * table 79 from FAPIv1.1 doc
87 uint8_t rgSchNumOfAcksToAckNack[RG_SCH_MAX_NUM_EXPECTED_ACKS][RG_SCH_NUM_FDBK_VALUE] = {
88 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
89 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
90 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
91 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
92 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
93 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
94 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
95 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
96 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK}
104 static Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, uint8_t tbIdx, uint8_t fdbk,
105 Bool maxHqRetxReached));
106 void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
108 static S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
109 RgSchDlHqProcCb *hqP,
116 static S16 rgSCHDhmUpdateAckNackHistory ARGS((
124 static Void rgSCHDhmPrcSplBundlFdbk ARGS((
130 static Void rgSchGetHqFdbkPosForM1 ARGS((
132 RgSchDlHqProcCb *hqP,
136 RgSchTddANInfo *anInfo
138 static Void rgSchGetHqFdbkPosForM234 ARGS((
140 RgSchDlHqProcCb *hqP,
144 RgSchTddANInfo *anInfo,
146 CmLteTimingInfo timeInfo
151 /* Freeing up the HARQ proc blocked for
152 * indefinite time in case of Retx */
153 S16 rgSCHDhmDlRetxAllocFail ARGS((
155 RgSchDlHqProcCb *proc
159 S16 rgSCHDhmEmtcRgrCellCfg ARGS((
165 uint32_t gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
166 uint32_t gSCellSchedCount,gPrimarySchedCount;
167 uint32_t gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
168 uint32_t gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
169 uint32_t gHqFdbkCount;
173 Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
175 RgSchEmtcDlSf *subFrm,
176 RgSchDlHqProcCb *hqP,
180 RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
185 Void rgSCHEmtcHqInfoAlloc ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP));
187 /* forward references */
190 * @brief This function initializes the DL HARQ Entity of UE.
194 * Function: rgSCHDhmHqEntInit
195 * Purpose: This function initializes the DL HARQ entity of
196 * UE control block. This is performed at the time
197 * of creating UE control block.
199 * Invoked by: configuration module
201 * @param[in] RgSchCellCb* cell
202 * @return RgSchDlHqEnt *
205 /*MS_WORKAROUND for ccpu00122893*/
206 Void rgSCHDhmHqEntReset(RgSchDlHqEnt *hqE)
208 RgSchDlHqProcCb *hqP;
210 cmLListInit(&hqE->inUse);
211 cmLListInit(&hqE->free);
212 for (i=0; i < hqE->numHqPrcs; i++)
214 hqP = &hqE->procs[i];
217 /* Fix - reset numLch */
218 hqP->tbInfo[0].numLch = 0;
219 hqP->tbInfo[1].numLch = 0;
220 hqP->tbInfo[0].txCntr = 0;
221 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
222 hqP->tbInfo[1].txCntr = 0;
223 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
224 hqP->tbInfo[0].tbIdx = 0;
225 hqP->tbInfo[1].tbIdx = 1;
226 hqP->tbInfo[0].hqP = hqP;
227 hqP->tbInfo[1].hqP = hqP;
228 hqP->tbInfo[0].state = HQ_TB_ACKED;
229 hqP->tbInfo[1].state = HQ_TB_ACKED;
230 hqP->tbInfo[0].contResCe = NOTPRSNT;
231 hqP->tbInfo[1].contResCe = NOTPRSNT;
232 hqP->lnk.node = (PTR)hqP;
233 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
235 rgSCHDhmHqPAdd2FreeLst(hqP);
236 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
237 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
238 hqP->drxCb.rttIndx = DRX_INVALID;
239 hqP->drxCb.reTxIndx = DRX_INVALID;
240 hqP->tbInfo[0].cntrRetxAllocFail = 0;
241 hqP->tbInfo[1].cntrRetxAllocFail = 0;
242 hqP->hasDcch = FALSE;
243 hqP->cwSwpEnabled = FALSE;
248 rgSCHLaaResetDlHqProcCb(hqP);
252 } /* rgSCHDhmHqEntReset */
255 * @brief This function assigns dlHqEnt of raCb to ueCb.
259 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
260 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
262 * Invoked by: configuration module
264 * @param[in] RgSchUeCb *ue
265 * @param[in] RgSchRaCb *raCb
269 Void rgSCHDhmAssgnUeHqEntFrmRaCb(RgSchUeCb *ue,RgSchRaCb *raCb)
272 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
273 ue->cellInfo[0]->hqEnt->ue = ue;
274 /* Update the DL Harq related information */
275 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
277 /* Fix : set UE active in DL as UE initialization completed */
278 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
279 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
280 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
286 * @brief This function deletes the dlHqEnt.
290 * Function: rgSCHDhmDelHqEnt
291 * Purpose: This function deletes the dlHqEnt.
293 * Invoked by: configuration module
295 * @param[in] RgSchCellCb *cell
296 * @param[in] RgSchDlHqEnt **hqE
300 Void rgSCHDhmDelHqEnt(RgSchCellCb *cell,RgSchDlHqEnt **hqE)
308 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
310 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
311 sizeof(RgSchDlHqEnt));
316 RgSchDlHqEnt *rgSCHDhmHqEntInit(RgSchCellCb *cell)
319 Inst inst = cell->instIdx;
321 /* Init the HARQ data structure */
322 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
324 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
325 "rgSCHDhmHqEntInit hqE alloc fail");
329 /* Init the HARQ processes */
330 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
331 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
332 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
334 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
335 "rgSCHDhmHqEntInit hqP alloc fail in hqE");
339 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
343 rgSCHLaaInitDlHqProcCb (cell, hqE);
346 /* Initialize maximum tranmission counter */
347 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
350 /* MW_WORKAROUND for ccpu00122893 */
351 rgSCHDhmHqEntReset(hqE);
357 } /* rgSCHDhmHqEntInit */
360 * @brief This function gets an available HARQ process.
364 * Function: rgSCHDhmGetAvlHqProc
365 * Purpose: This function returns an available HARQ process in
366 * the DL direction. All HARQ processes are maintained
367 * in queues of free and inuse.
369 * 1. Check if the free queue is empty. If yes, return
371 * 2. If not empty, update the proc variable with the
372 * first process in the queue. Return ROK.
374 * Invoked by: scheduler
376 * @param[in] RgSchUeCb *ue
377 * @param[in] CmLteTimingInfo timingInfo
378 * @param[out] RgSchDlHqProc **hqP
380 * -#ROK if successful
381 * -#RFAILED otherwise
384 S16 rgSCHDhmGetAvlHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo,RgSchDlHqProcCb **hqP)
386 RgSchDlHqEnt *hqE = NULLP;
387 RgSchDlHqProcCb *tmpHqProc;
390 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
394 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDhmGetAvlHqProc hqE NULL ue %d"
400 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
404 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
405 "rgSCHDhmGetAvlHqProc free %ld inUse %ld ue %d"
406 , hqE->free.count, hqE->inUse.count, ue->ueId);
407 /* No Harq Process available in the free queue. */
411 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
414 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
416 if (ue->dl.isSpsHqPInUse)
418 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
420 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
425 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
429 /* No Harq Process available in the free queue. */
436 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
437 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
438 tmpHqProc->hasDcch = FALSE;
439 tmpHqProc->cwSwpEnabled = FALSE;
441 /* Remove the element from the free Queue */
442 //cmLListDelFrm(&hqE->free, tmp);
443 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
445 /* Add the element into the inUse Queue as well */
446 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
447 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
452 rgSCHLaaResetDlHqProcCb(tmpHqProc);
456 tmpHqProc->tbSizeAtEstimate[0] = 0;
457 tmpHqProc->tbSizeAtEstimate[1] = 0;
458 tmpHqProc->tbSizeAtFnlz[0] = 0;
459 tmpHqProc->tbSizeAtFnlz[1] = 0;
460 tmpHqProc->tbSizeOfMvdTb[0] = 0;
461 tmpHqProc->tbSizeOfMvdTb[1] = 0;
462 tmpHqProc->itbsAtEstimate[0] = 0;
463 tmpHqProc->itbsAtEstimate[1] = 0;
464 tmpHqProc->prbAtEstimate = 0;
467 } /* rgSCHDhmGetAvlHqProc */
471 * @brief This function adds HARQ process for a given TB in to
472 * the inuse queue upon retx.
476 * Function: rgSCHDhmHqTbRetx
477 * Purpose: This function handles when a HARQ process is scheduled
478 * for retransmission. It adds the HARQ procss to inuse
480 * 1. Check if this HqP is already added to the inUse
481 * queue as part of this function call for other
482 * TB's retransmission.
483 * 2. If already present in inUse Q then do not add.
485 * Invoked by: scheduler
487 * @param[in] RgSchDlHqEnt *hqE
488 * @param[in] CmLteTimingInfo timingInfo
489 * @param[out] RgDlHqProc *hqP
490 * @param[in] uint8_t tbIdx
494 Void rgSCHDhmHqTbRetx(RgSchDlHqEnt *hqE,CmLteTimingInfo timingInfo,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
496 uint8_t othrTbIdx = tbIdx ^ 1;
498 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
500 if (hqE->msg4Proc == hqP)
504 /* fix for ccpu00118633 No Hq proc Avl end*/
506 /* Extra:check if Harq process is already linked to in-use
507 Queue by means of other TB handling. */
508 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
511 if (hqE->msg4Proc != hqP)
513 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
514 rgSCHDhmHqPAdd2InUseLst(hqP);
518 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
521 } /* rgSCHDhmHqTbRetx */
524 * @brief This function returns last scheduled HARQ process for
525 * a UE's HARQ entity.
529 * Function: rgSCHDhmLastSchedHqProc
530 * Purpose: This function returns the last (most recent)
531 * process in the inUse list, which corresponds
532 * to the last scheduled process. Returns NULLP
534 * The reason for introducing this is to have
535 * an ability to check if UE was scheduled
536 * in the current subframe (scheduling would
537 * have caused a proc to be added to the end
538 * of the list, and checking time (only subframe
539 * number probably works) would confirm this.
541 * Invoked by: scheduler
543 * @param[in] RgSchDlHqEnt *hqE
544 * @return RgSchDlHqProcCb *
547 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(RgSchDlHqEnt *hqE)
549 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
550 * until RACH procedure is completed */
551 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
555 return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
556 } /* rgSCHDhmLastSchedHqProc */
560 * @brief This function gets an available HARQ process for MSG 4.
564 * Function: rgSCHDhmGetCcchSduHqProc
565 * Purpose: This function returns an available HARQ process in
566 * the DL direction. All HARQ processes are maintained
567 * in queues of free and inuse.
569 * 1. Check if the free queue is empty. If yes, return
571 * 2. If not empty, update the proc variable with the
572 * first process in the queue. Return ROK.
574 * Invoked by: scheduler
576 * @param[in] RgSchRaCb *raCb
577 * @param[in] CmLteTimingInfo timingInfo
578 * @param[out] RgSchDlHqProcCb **hqP
580 * -#ROK if successful
581 * -#RFAILED otherwise
584 S16 rgSCHDhmGetCcchSduHqProc
587 CmLteTimingInfo timingInfo,
588 RgSchDlHqProcCb **hqP
591 RgSchDlHqProcCb *tmpHqProc;
595 hqE = ueCb->cellInfo[0]->hqEnt;
596 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
599 /* No Harq Process available in the free queue. */
603 /* Remove the element from the free Queue and */
604 /* set the MSG 4 HARQ proc pointer */
605 //cmLListDelFrm(&hqE->free, tmp);
607 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
609 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
611 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
612 /* Fix : syed minor code reorg */
614 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
616 hqE->ccchSduProc = tmpHqProc;
617 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
618 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
621 } /* rgSCHDhmGetCcchSduHqProc */
625 * @brief This function gets an available HARQ process for MSG 4.
629 * Function: rgSCHDhmGetMsg4HqProc
630 * Purpose: This function returns an available HARQ process in
631 * the DL direction. All HARQ processes are maintained
632 * in queues of free and inuse.
634 * 1. Check if the free queue is empty. If yes, return
636 * 2. If not empty, update the proc variable with the
637 * first process in the queue. Return ROK.
639 * Invoked by: scheduler
641 * @param[in] RgSchRaCb *raCb
642 * @param[in] CmLteTimingInfo timingInfo
643 * @param[out] RgDlHqProc **hqP
645 * -#ROK if successful
646 * -#RFAILED otherwise
649 S16 rgSCHDhmGetMsg4HqProc(RgSchRaCb *raCb,CmLteTimingInfo timingInfo)
651 RgSchDlHqProcCb *tmpHqProc;
656 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
659 /* No Harq Process available in the free queue. */
663 /* Remove the element from the free Queue and */
664 /* set the MSG 4 HARQ proc pointer */
665 //cmLListDelFrm(&hqE->free, tmp);
666 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
667 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
668 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
669 hqE->msg4Proc = tmpHqProc;
672 } /* rgSCHDhmGetMsg4HqProc */
675 * @brief This function releases a HARQ process.
679 * Function: rgSCHDhmRlsHqpTb
680 * Purpose: This function resets the TB specific fields
681 * Based on the other TBs state, this HqProcess
682 * is returned to the HqEnt.
684 * 1. Add the HARQ process to the free queue.
685 * Invoked by: scheduler and HARQ processing
687 * @param[in] RgDlHqProc *hqP
688 * @param[in] uint8_t tbIdx
689 * @param[in] Bool togNdi
693 Void rgSCHDhmRlsHqpTb(RgSchDlHqProcCb *hqP,uint8_t tbIdx,Bool togNdi)
696 uint8_t othrTbIdx = tbIdx ^ 1;
698 RgSchCmnDlHqProc *cmnHqDl;
702 RgSchDlLcCb* lcCb = NULLP;
706 /* Reset all tbInfo values */
711 if (hqP->hqE->ue != NULLP)
713 RgSchUeCb *ueCb = hqP->hqE->ue;
714 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
715 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
716 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
717 /* to get retransmission, decreasing transmission counter */
718 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
719 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
720 static uint32_t retxCnt1 = 0;
722 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
723 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
728 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
731 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
734 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
737 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
740 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
741 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
742 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
743 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
744 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
746 retxCnt1 += numDlRetx;
748 #endif /* MAC_SCH_STATS */
749 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
753 hqP->tbInfo[tbIdx].ndi ^= 1;
758 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
760 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
761 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
763 if (lcCb->lcType == CM_LTE_LCH_DTCH)
765 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
767 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
770 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
772 lcCb->qciCb->dlUeCount--;
780 hqP->tbInfo[tbIdx].tbSz = 0;
781 hqP->tbInfo[tbIdx].numLch = 0;
782 hqP->tbInfo[tbIdx].txCntr = 0;
783 /* FOR ACK NACK REP */
784 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
785 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
786 hqP->tbInfo[tbIdx].ackCount = 0;
787 /* pdcch is moved from TbCb to HqCb.
788 This pdcch will be set to NULL when
789 HqCb will be pushed to free list*/
790 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
791 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
792 hqP->tbInfo[tbIdx].nackCount = 0;
793 hqP->tbInfo[tbIdx].dtxCount = 0;
794 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
795 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
797 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
799 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
800 /* Handling msg4 hqProc */
801 if (hqE->msg4Proc == hqP)
803 hqE->msg4Proc = NULLP;
806 /* Add the proc to the free list */
807 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
808 rgSCHDhmHqPAdd2FreeLst(hqP);
812 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
813 * is dangerous and it expects ccchSduProc is the first
814 * DL allocation for a UE, and considering a scenario
815 * of multiple UEs contending and 1 UE per TTI, this
816 * assumption can be wronged, leading to inUse list
817 * corruption. Hence altering this check.
818 * A better approach would be do avoid having this
819 * special handling for ccchSduProc, streamline
820 * it with the usual approach. */
821 if (hqE->ccchSduProc == hqP)
823 hqE->ccchSduProc = NULLP;
824 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
825 * in inUse list, Hence need not to delete from inUse list*/
826 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
828 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
829 rgSCHDhmHqPDelFrmInUseLst(hqP);
833 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
837 /* Add the proc to the free list */
838 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
839 rgSCHDhmHqPAdd2FreeLst(hqP);
844 /* extra:check if other TB is also free for allocation then
845 * add it to FREE List */
846 switch(hqP->tbInfo[othrTbIdx].state)
849 /* Remove the element from the inUse Queue */
850 /* Freeing up the HARQ proc blocked for
851 * indefinite time in case of Retx */
852 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
854 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
855 rgSCHDhmHqPDelFrmInUseLst(hqP);
860 rgEmtcsetNullSubFrm(hqP);
862 /* Add the proc to the free list */
863 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
864 rgSCHDhmHqPAdd2FreeLst(hqP);
866 if (hqE->free.count > 8)
869 printf("Crashing invalid hq count after free \n");
870 printf("Crashing %d \n", *p);
875 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
878 cmnHqDl->spsAction = 0;
879 cmnHqDl->isSpsActv = FALSE;
880 cmnHqDl->isSpsSvcSchd = FALSE;
885 /* Remove the element from the inUse Queue */
886 /* Freeing up the HARQ proc blocked for
887 * indefinite time in case of Retx */
888 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
890 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
891 rgSCHDhmHqPDelFrmInUseLst(hqP);
899 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
902 } /* rgSCHDhmRlsHqpTb */
905 * @brief This function releases a HARQ process.
909 * Function: rgSCHDhmRlsHqProc
910 * Purpose: This function returns a HARQ process to HARQ Entity
911 * in the DL direction.
913 * 1. Add the HARQ process to the free queue.
914 * Invoked by: scheduler and HARQ processing
916 * @param[in] RgDlHqProc *hqP
920 Void rgSCHDhmRlsHqProc(RgSchDlHqProcCb *hqP)
925 /* THIS FUNCTION IS NOT CALLED */
926 if (hqP->hqE->ue != NULLP)
928 RgSchUeCb *ueCb = hqP->hqE->ue;
929 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
930 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
931 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
932 /* to get retransmission, decreasing transmission counter */
933 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
934 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
936 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
941 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
944 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
947 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
950 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
953 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
954 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
955 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
956 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
957 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
959 #endif /* MAC_SCH_STATS */
963 rgEmtcsetNullSubFrm(hqP);
965 rgSCHDhmHqPDelFrmInUseLst(hqP);
966 rgSCHDhmHqPAdd2FreeLst(hqP);
972 } /* rgSCHDhmRlsHqProc */
976 * @brief This function gets HARQ process with the given ID.
980 * Function: rgSCHDhmGetHqProcFrmId
981 * Purpose: This function returns the HARQ process with the given ID.
984 * @param[in] RgSchUeCb *ue
985 * @param[in] uint8_t idx
986 * @param[in] RgDlHqProc **hqP
988 * -# ROK if successful
989 * -# RFAILED otherwise
992 S16 rgSCHDhmGetHqProcFrmId(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t idx,RgSchDlHqProcCb **hqP)
996 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
997 /* Pick the proc based on the index provided */
998 *hqP = &(hqE->procs[idx]);
1001 } /* rgSCHDhmGetHqProcFrmId */
1004 * @brief This function gets SPS HARQ process from the given time
1008 * Function: rgSCHDhmSpsDlGetHqProc
1009 * Purpose: This function returns the SPS HARQ process for the given time
1011 * @param[in] RgSchUeCb *ue
1012 * @param[in] CmLteTimingInfo timingInfo
1013 * @return RgSchDlHqProcCb control block
1016 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
1020 RgSchDlHqProcCb *hqProc = NULLP;
1021 CmLList *tmp = NULLP;
1023 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1025 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1029 /* No Harq Process available in the free queue. */
1033 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1034 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1037 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1039 /* If the HARQ process is in the free list, retrieve the process */
1040 while (hqProc->procId != idx)
1042 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1047 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1052 /* No Harq Process available in the free queue. */
1056 hqProc->tbInfo[0].timingInfo = timingInfo;
1057 hqProc->tbInfo[1].timingInfo = timingInfo;
1059 /* Remove the element from the free Queue */
1060 //cmLListDelFrm(&hqE->free, tmp);
1061 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1063 /* Add the element into the inUse Queue as well */
1064 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1065 rgSCHDhmHqPAdd2InUseLst(hqProc);
1068 rgSCHLaaResetDlHqProcCb(hqProc);
1072 } /* rgSCHDhmSpsDlGetHqProc */
1073 #endif /* LTEMAC_SPS */
1076 /** * @brief Handler for handling TA.
1080 * Function : rgSCHDhmFdbkIndHndlTa
1082 * This function handles the TA state and values based on the
1083 * feedback indication received.
1085 * @param[in] RgSchDlHqProcCb *hqP
1086 * @param[in] uint8_t tbIdx
1087 * @param[in] uint8_t fdbk
1091 static Void rgSCHDhmFdbkIndHndlTa(RgSchDlHqProcCb *hqP,uint8_t tbIdx,uint8_t fdbk,Bool maxHqRetxReached)
1096 ueCb = hqP->hqE->ue;
1101 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1102 hqP->tbInfo[tbIdx].taSnt = FALSE;
1103 /* To prevent duplicate inserts of ueCb into TA list */
1104 if (ueCb->taLnk.node == NULLP)
1106 ueCb->taLnk.node = (PTR)ueCb;
1107 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1112 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Trying to add CRNTI:%d into TA"
1113 "ACK List twice", ueCb->ueId);
1119 /* If Ta was sent and its the final NACK, then reset only the
1120 * taState to IDLE and not the value */
1121 /* Changed handling in case maxhqretx is reached for TA */
1122 if(TRUE == maxHqRetxReached)
1124 hqP->tbInfo[tbIdx].taSnt = FALSE;
1125 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1127 rgSCHUtlReTxTa(cell, ueCb);
1128 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
1129 "Nack Rcvd for TA. Max Tries Attempted");
1133 /* If Ta was sent and its the final NACK, then reset only the
1134 * taState to IDLE and not the value */
1135 if(TRUE == maxHqRetxReached)
1137 hqP->tbInfo[tbIdx].taSnt = FALSE;
1138 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1140 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1141 * issue for VoLTE call */
1142 rgSCHUtlDlTARpt(cell, ueCb);
1151 } /* rgSCHDhmFdbkIndHndlTa */
1153 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1154 /** * @brief Handler for scheduling TA.
1158 * Function : rgSCHDhmShcdTa
1160 * This function is called by scheduler when resource allocation
1161 * for TA transmission is done.
1163 * @param[in] RgSchUeCb *ue
1164 * @param[out] RgSchDlHqTbCb *tbInfo
1168 Void rgSCHDhmSchdTa(RgSchUeCb *ueCb,RgSchDlHqTbCb *tbInfo)
1171 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1172 ueCb->dl.taCb.numRemSf = 2;
1173 tbInfo->schdTa.pres = PRSNT_NODEF;
1174 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1177 } /* rgSCHDhmSchdTa */
1180 /** * @brief Handler for fetching Harq Proc given the feeback information.
1184 * Function : rgSCHDhmHqProcByFdbkTime
1186 * This function shall fetch all the harq proc having the feedback
1187 * timing information.
1189 * @param[in] RgSchDlHqEnt *hqE
1190 * @param[in] CmLteTimingInfo timeInfo
1191 * @param[in] Bool *isMsg4
1192 * @param[out] RgSchDlHqProcCb **hqPrcs
1193 * @param[out] uint8_t *numTbs
1194 * @param[out] S8 *tbStrtIdx
1195 * @param[out] uint8_t *cntHqPrcs
1198 static S16 rgSCHDhmHqProcByFdbkTime
1201 CmLteTimingInfo timeInfo,
1203 RgSchDlHqProcCb **hqPrcs,
1210 RgSchDlHqTbCb *tbCb;
1211 RgSchDlHqProcCb *hqP;
1212 CmLteTimingInfo schdSfTime;
1213 RgSchTddDlAscSetIdxK ascIdx;
1224 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1227 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1228 tbStrtIdx[*cntHqPrcs] = 0;
1229 numTbs[*cntHqPrcs] = 1;
1234 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1235 noFdbks = ascIdx.numFdbkSubfrms;
1237 for(idx=0; idx<noFdbks; idx++)
1239 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1240 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1241 * serving the purpose */
1242 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1243 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1244 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1248 hqP = (RgSchDlHqProcCb*)node->node;
1251 numTbs[*cntHqPrcs] = 0;
1252 tbStrtIdx[*cntHqPrcs] = -1;
1253 for (i = 0; i < 2; i++)
1255 /* Extra:check which TB is waiting for feedback */
1256 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1258 if (tbStrtIdx[*cntHqPrcs] == -1)
1260 tbStrtIdx[*cntHqPrcs] = i;
1262 numTbs[*cntHqPrcs]++;
1265 if (numTbs[*cntHqPrcs] > 0)
1267 hqPrcs[*cntHqPrcs] = hqP;
1272 /* AN REP Hq Procs */
1273 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1276 tbCb = (RgSchDlHqTbCb *)(node->node);
1279 numTbs[*cntHqPrcs] = 0;
1280 tbStrtIdx[*cntHqPrcs] = -1;
1281 for (i = 0; i < 2; i++)
1283 /* Extra:check which TB is waiting for feedback */
1284 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1286 if (tbStrtIdx[*cntHqPrcs] == -1)
1288 tbStrtIdx[*cntHqPrcs] = i;
1290 numTbs[*cntHqPrcs]++;
1293 if (numTbs[*cntHqPrcs] == 2)
1297 if (numTbs[*cntHqPrcs] > 0)
1299 hqPrcs[*cntHqPrcs] = hqP;
1311 /** * @brief Handler for fetching Harq Proc given the timming information.
1315 * Function : rgSCHDhmHqProcByTime
1317 * This function shall fetch the harq proc using the timing information.
1319 * @param[in] RgSchDlHqEnt *hqE
1320 * @param[in] CmLteTimingInfo timeInfo
1321 * @param[in] Bool *isMsg4
1322 * @param[out] uint8_t *numTbs
1323 * @param[out] S8 *tbStrtIdx
1324 * @return RgSchDlHqProcCb*
1325 * -# RgSchDlHqProcCb*
1328 RgSchDlHqProcCb *rgSCHDhmHqProcByTime(RgSchDlHqEnt *hqE,CmLteTimingInfo timeInfo,Bool *isMsg4,RgSchDlSf *sf)
1332 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1335 return (hqE->msg4Proc);
1343 /** * @brief Handler for handling the harq transaction failure.
1347 * Function : rgSCHDhmHqTbTrnsFail
1349 * This function handled the harq TB transaction failure :
1350 * - If retries have not reached maximum, add to the reTx Q.
1351 * - else do error recovery.
1353 * @param[in] RgSchCellCb *cell
1354 * @param[in] RgSchDlHqProcCb *hqP
1355 * @param[in] uint8_t tbCnt
1356 * @param[out] Bool *isMaxRetx
1361 Void rgSCHDhmHqTbTrnsFail(RgSchCellCb *cell,RgSchDlHqProcCb *hqP,uint8_t tbCnt,Bool *isMaxRetx)
1368 /* Fetch the maximum number of harq transmissions */
1369 if (hqE->msg4Proc == hqP)
1372 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1374 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1375 "rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1376 hqP->hqE->raCb->tmpCrnti);
1377 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1381 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1385 maxHqTx = hqE->maxHqTx;
1388 #ifdef MAC_SCH_STATS
1389 if (hqE->ue != NULLP)
1391 RgSchUeCb *ueCb = hqE->ue;
1392 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1393 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1394 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1395 static uint32_t retxCnt = 0;
1399 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1401 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1402 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1404 #endif /* MAC_SCH_STATS */
1406 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1407 /* Reset the PDCCH reference */
1409 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1411 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1413 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1416 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1417 * for the UE. Addtion to the retransmission queue will be done on
1418 * HARQ RTT timer expiry.--*/
1419 switch(hqP->tbInfo[tbCnt ^ 1].state)
1422 /*As the first TB is ACKED we have not started HARQ RTT for the
1423 * HqP, so start it here.*/
1424 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1425 rgSCHDhmHqPDelFrmInUseLst(hqP);
1427 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1430 /* Integration fix */
1431 /* Setting cntrRetxAllocFail to MAX value here */
1432 /* Since the hqP entry is already deleted from inUse list of HqEntity
1433 setting the value here will ensure the entry is not deleted
1434 again during release harq proc */
1435 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1436 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1438 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1439 if (hqP->tbInfo[1].txCntr)
1441 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1447 /*As the first TB is NACKED we have already started HARQ RTT for the
1448 * HqP, so dont start it here, just delete from in use queue.*/
1449 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1450 rgSCHDhmHqPDelFrmInUseLst(hqP);
1453 /*As this is the first TB to be fed back and is NACKED start
1454 * the HARQ RTT here.*/
1456 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1462 /* extra:check if already removed as part of other TB processing
1463 * then donot remove from InUse Q */
1464 /* Check if other TB is not waiting for feedback.
1465 * Makinf sure hqP is present in inUse Queue until
1466 * it is fedback for all its TBs */
1467 switch(hqP->tbInfo[tbCnt ^ 1].state)
1470 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1471 if(hqE->msg4Proc != hqP)
1473 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1474 rgSCHDhmHqPDelFrmInUseLst(hqP);
1476 /* Retransmission needs to be done. Add to the scheduler Q */
1477 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1480 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1481 if(hqE->msg4Proc != hqP)
1483 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1484 rgSCHDhmHqPDelFrmInUseLst(hqP);
1488 /* Retransmission needs to be done. Add to the scheduler Q */
1490 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1498 /* Failure Notification */
1499 if (hqE->msg4Proc == hqP)
1501 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1502 rgNumMsg4FailMaxRetx++;
1504 hqE->cell->tenbStats->sch.msg4Fail ++;
1507 /* Perform RAM MSG4 done processing */
1508 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1509 "rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1510 hqP->hqE->raCb->tmpCrnti);
1511 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1515 /* Release the Harq Proc */
1516 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1522 } /* rgSCHDhmHqTbTrnsFail */
1524 uint32_t rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1525 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1528 /** * @brief Function to decode the position of HarqFb for M=1.
1532 * Function : rgSchGetHqFdbkPosForM1
1534 * @param[in] RgSchUeCb *ue,
1535 * @param[in] RgSchDlHqProcCb *hqP,
1536 * @param[in] uint8_t *isAck,
1537 * @param[in] RgTfuHqInfo *fdbk,
1538 * @param[in] uint8_t tbIdx,
1539 * @param[in] RgSchTddANInfo *anInfo;
1542 static Void rgSchGetHqFdbkPosForM1
1545 RgSchDlHqProcCb *hqP,
1549 RgSchTddANInfo *anInfo
1554 /* handle pusch and pucch cases */
1555 /* PUSCH:: Fdbks are in the increasing order
1556 * of servCellIdx as per 36.212 section 5.2.26*/
1557 switch(ue->f1bCsAVal)
1559 case RG_SCH_A_VAL_2:
1561 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1563 *isAck = fdbk->isAck[1];/*SCell*/
1567 *isAck = fdbk->isAck[0];/*PCell*/
1571 case RG_SCH_A_VAL_3:
1573 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1575 uint8_t cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1576 hqP->hqE->cell->cellId,
1579 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1580 {/*SCell - mimo mode*/
1581 if(TRUE == fdbk->isPusch)
1583 *isAck = fdbk->isAck[tbIdx + 1];
1587 *isAck = fdbk->isAck[tbIdx];
1591 {/*SCell - siso mode*/
1592 *isAck = fdbk->isAck[2];
1596 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1597 {/*Primary Cell - mimo mode*/
1598 *isAck = fdbk->isAck[tbIdx];
1601 {/*Primary Cell - siso mode*/
1602 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1604 /* If fdbk is on PUSCH but its not an SPS occasion*/
1605 *isAck = fdbk->isAck[0];
1609 /* If fdbk is on PUCCH or its an SPS occasion*/
1610 *isAck = fdbk->isAck[2];
1616 case RG_SCH_A_VAL_4:
1618 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1620 *isAck = fdbk->isAck[tbIdx + 2];
1624 *isAck = fdbk->isAck[tbIdx];
1633 }/* End of rgSchGetHqFdbkPosForM1 */
1635 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1639 * Function : rgSchGetHqFdbkPosForM234
1641 * @param[in] RgSchUeCb *ue,
1642 * @param[in] RgSchDlHqProcCb *hqP,
1643 * @param[in] uint8_t *isAck,
1644 * @param[in] RgTfuHqInfo *fdbk,
1645 * @param[in] uint8_t tbIdx,
1646 * @param[in] RgSchTddANInfo *anInfo;
1647 * @param[in] CmLteTimingInfo timeInfo;
1650 static Void rgSchGetHqFdbkPosForM234
1653 RgSchDlHqProcCb *hqP,
1657 RgSchTddANInfo *anInfo,
1659 CmLteTimingInfo timeInfo
1664 RgSchTddANInfo *pCellAnInfo;
1669 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1670 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1672 if(TRUE == fdbk->isPusch)
1676 if (anInfo->wUlDai == 3)
1678 incr = anInfo->wUlDai;
1684 if(1 == anInfo->ulDai)
1686 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1687 hqP->tbInfo[tbIdx].tbIdx + incr;
1691 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1696 if(1 == anInfo->ulDai)
1698 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1700 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1704 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1709 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1717 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1718 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1724 /* SPS occasion feedback in case of M > 2 will
1725 * be always present in the index 0*/
1727 if(hqP->spsN1PucchRes.pres == TRUE)
1728 {/* SPS occasion hq proc */
1732 if((NULLP != pCellAnInfo) &&
1733 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1735 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1737 {/* NO SPS occasion was present in the bundle*/
1738 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1743 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1747 *isAck = fdbk->isAck[fdbkIdx];
1749 static RgSchDlHqProcCb *temp = NULLP;
1750 if (temp != hqP->tbInfo[tbIdx].hqP)
1752 statsCnt = statsCnt % 10000;
1753 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
1754 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
1755 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot;
1756 dlHqStats[statsCnt].ack = *isAck;
1757 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
1758 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;
1760 dlHqStats[statsCnt].ulDai = incr;
1761 if(TRUE == fdbk->isPusch)
1763 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
1767 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1771 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
1772 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
1773 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
1774 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
1775 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
1776 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
1777 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
1778 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
1781 temp = hqP->tbInfo[tbIdx].hqP;
1786 }/*rgSchGetHqFdbkPosForM234*/
1790 * @brief Handler for HARQ feedback received for DL transmission.
1794 * Function : rgSCHDhmHqFdbkInd
1796 * This function shall act on the feedback received from TOM for DL
1797 * transmission. If the feedback for msg4 is final (after max transmissions
1798 * or ACK) inform RAM that Msg4 transmission is done.
1801 * @param[in] Void *cb
1802 * @param[in] uint8_t cbType
1803 * @param[in] RgSchCellCb cellCb
1804 * @param[in] CmLteTimingInfo timeInfo
1805 * @param[in] TfuHqInfo *fdbk
1806 * @param[in] RgInfRlsHqInfo *rlsHqBufs
1807 * @param[in] RgSchErrInfo *err
1812 S16 rgSCHDhmHqFdbkInd
1816 RgSchCellCb *cellCb,
1817 CmLteTimingInfo timeInfo,
1819 RgInfRlsHqInfo *rlsHqBufs,
1823 RgSchCellCb *sCell = NULLP;
1825 /*ccpu00127339 - MOD - change to avoid the crash*/
1826 RgSchUeCb *ue = NULLP;
1828 Bool isMsg4 = FALSE;
1829 RgSchRaCb *raCb = NULLP;
1831 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
1832 * given feedback at a time */
1833 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
1834 uint8_t numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
1835 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
1838 RgSchTddANInfo *anInfo = NULLP;
1841 RgrTddAckNackMode ackNackMode;
1843 RgSchDlSf *nxtDlsf = NULLP;
1844 /* uint8_t rcvCnt = 0; */
1845 CmLteTimingInfo nxtfrm = {0,0};
1847 Bool maxHqRetxReached;
1849 Bool hasRelPdcch = FALSE;
1852 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1853 RgSchTddDlAscSetIdxK ascIdx;
1857 #ifdef LTEMAC_SPS_AN_MUX
1858 Bool isPusch = FALSE;
1861 /* Subframes in which transmissions are scheduled and whose feedback can come
1862 * in this subframe. Used only for Multiplexing mode */
1863 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
1864 #ifdef RGSCH_SPS_STATS
1865 RgSchCmnDlHqProc *cmnHqDl;
1869 uint8_t sCellActCePres = 0;
1871 /* LTEMAC_SPS_AN_MUX*/
1872 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
1874 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
1876 raCb = (RgSchRaCb *)(cb);
1877 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
1879 /* ccpu00139061 Fix */
1880 rnti = raCb->tmpCrnti;
1884 ue = (RgSchUeCb *)(cb);
1885 ackNackMode = ue->dl.ackNackMode;
1886 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
1888 #ifdef LTEMAC_SPS_AN_MUX
1889 isPusch = fdbk->isPusch;
1893 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
1900 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1901 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
1902 noFdbks = ascIdx.numFdbkSubfrms;
1904 #ifdef LTEMAC_SPS_AN_MUX
1905 /* Calculate the subframe time at which transmissions should have happened to
1906 * receive feedback in this subframe */
1907 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
1909 for(idx=0; idx<noFdbks; idx++)
1911 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1912 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1913 * serving the purpose */
1914 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
1919 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
1920 tbStrtIdx, &hqCnt,hqE->cell);
1921 /* Fetch the harqProc from the inUse list */
1923 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
1927 err->errType = RGSCHERR_DHM_FDBK_IND;
1928 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
1932 /* ccpu00147469 : This code is moved below as here this code always try to
1933 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
1937 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
1939 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
1945 #ifdef LTEMAC_SPS_AN_MUX
1946 /* Check if feedback came on configured UL SPS grant in Muxing mode */
1947 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
1951 /* Pick the valid feedbacks out of M feedbacks */
1952 for(idx=0; idx<noFdbks; idx++)
1954 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
1955 * and no release pdcch is sent in prevTime */
1956 /* TODO: SPS_TDD: Check this while testing */
1957 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
1958 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
1959 schdSfTime[idx])) &&
1960 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
1962 /* Discard the feedback which is corresponding to a subframe in
1963 * which no DL transmission took place */
1965 while(tmpIdx < noFdbks)
1967 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1968 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1974 } /* end of for loop */
1975 } /* end of configured UL SPS grant check */
1987 for(idx=0;idx < hqCnt; idx++)
1989 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
1993 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
1994 hqPrcs[idx]->hqE->cell->cellId,ue);
1996 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
2000 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
2002 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
2006 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
2007 "Ack Rcvd. No Ack/Nack feedback available \n"));
2012 sCell = hqPrcs[idx]->hqE->cell;
2013 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2014 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2015 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2017 /* Fix : syed MultiUe per TTI crash in TA List. */
2019 maxHqRetxReached = FALSE;
2020 /* Remove the harq process from the subframe */
2021 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2025 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2028 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2030 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2031 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2033 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2037 /* TODO: review for TM4 and CA interaction */
2038 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2040 isAck = fdbk->isAck[!tbCnt];
2044 isAck = fdbk->isAck[tbCnt];
2053 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2057 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2063 /* revanth tweakin AN PUSCH to ACK always */
2064 if (hqPrcs[idx]->isPuschFdbk)
2070 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2071 if(cellCb->ulDlCfgIdx != 5)
2073 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2074 cellCb, sf, &nxtDlsf, &nxtfrm);
2076 /* Keep a tab on how many ACKs or NACKs we have received */
2077 if (isAck == TFU_HQFDB_ACK)
2079 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2080 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2082 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2083 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2085 /* Do not update the Ul Trans Time in case of raCb */
2088 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2090 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2094 else if (isAck == TFU_HQFDB_NACK)
2096 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2097 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2099 sCell->tenbStats->sch.dlNack[tbCnt]\
2100 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2101 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2102 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2104 /* Do not update the Ul Trans Time in case of raCb */
2107 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2109 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2110 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2114 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2116 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2122 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2124 sCell->tenbStats->sch.dlDtx[tbCnt]\
2125 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2128 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2132 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2134 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2139 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2141 if(isAck == TFU_HQFDB_ACK)
2143 gSCellTb1AckCount++;
2144 gSCellTb2AckCount++;
2145 }else if(isAck == TFU_HQFDB_NACK)
2147 gSCellTb1NackCount++;
2148 gSCellTb2NackCount++;
2151 gSCellTb1DtxCount++;
2152 gSCellTb2DtxCount++;
2157 if(isAck == TFU_HQFDB_ACK)
2159 gPCellTb1AckCount++;
2160 gPCellTb2AckCount++;
2161 }else if(isAck == TFU_HQFDB_NACK)
2163 gPCellTb1NackCount++;
2164 gPCellTb2NackCount++;
2167 gPCellTb1DtxCount++;
2168 gPCellTb2DtxCount++;
2172 /* Check if this is repeating UE */
2173 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2175 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2176 /* Check if last repetition */
2177 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2179 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2180 /* Update feedback time for this hqP TB so that
2181 * next subframe its picked up */
2182 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2184 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2185 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2189 /* For a repeating UE take the decision here */
2190 /* For a repeating UE take the decision here */
2191 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2192 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2194 isAck = TFU_HQFDB_ACK;
2196 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2197 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2199 isAck = TFU_HQFDB_DTX;
2203 isAck = TFU_HQFDB_NACK;
2205 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2209 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2212 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2213 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2214 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2217 /* ACK or NACK received for SPS ACTV PDCCH
2218 * Hence consider SPS ACTVN PDCCH received successfully */
2219 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2222 if(TFU_HQFDB_ACK == isAck)
2229 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2231 /* Inform Random Access Module regarding the ack received */
2234 /*RRC Connection Setup failure issue where RRC connection
2235 * setup was not reaching UE due to message 4 HARQ failure */
2236 #ifdef XEON_SPECIFIC_CHANGES
2237 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2239 rgSCHRamMsg4Done(cellCb, raCb);
2242 else /*ccpu00114124- HARQ Release for Msg4 */
2245 /*Update feedback history for every Tx/Retx */
2246 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2248 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2249 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2251 /* Store activation CE presence as it is required later to start
2252 *activation delay timer */
2253 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2255 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2261 /* If this Msg4 DTX, there will be
2262 * no DlHqProc as it has its own HarqProc */
2265 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2266 maxHqRetxReached = hqRls;
2268 if ((isMsg4 == FALSE))
2270 /*Update feedback history for every Tx/Retx */
2271 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2274 if (isMsg4 == FALSE)
2276 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2277 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2284 /* MS_WORKAROUND: to increase Harq Fail Counter .
2285 The status field is required for tracking the number of harq faliures at MAC*/
2288 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2289 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2293 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2294 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2296 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2297 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2298 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2302 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2304 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2307 /* Handle Scell activation */
2308 if (TRUE == sCellActCePres)
2310 /* Primary Cellcb needs to be retrived
2311 * if the feedback is coming on pusch of
2312 * sec cell. THis needs to be considered
2314 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2320 hqPrcs[idx]->cwSwpEnabled = FALSE;
2322 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2324 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2325 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2326 hqPrcs[idx]->procId;
2327 rlsHqBufs->numUes++;
2330 hqPrcs[idx]->isPuschFdbk = 0;
2335 /*it is possible for some TDD configurations (like TDD cfg 5)
2336 * to have multiple feedback for 13 subframes before. It is
2337 * possible in such a case to have a release sent after data
2338 * thus running into a situation where we are receiving feedback
2339 * for both data and relese pdcch
2342 if ( (hqCnt == 0) ||
2343 (hasRelPdcch && rcvCnt > hqCnt)
2346 if (ue && hasRelPdcch)
2348 /* Bool found = FALSE; */
2350 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2360 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2361 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2363 CmLteTimingInfo txTime;
2364 uint8_t ulDlCfgIdx = 0;
2365 uint8_t maxFdbks = 0;
2368 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2370 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2374 for(itr=0; itr< maxFdbks; itr++)
2377 /* Handling the case of only SPS release pdcch
2378 * and no other scheduling in both the serving cells
2380 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2381 {/* Using the sorted K table */
2382 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2383 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2387 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2388 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2391 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2394 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2397 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2399 isAck = fdbk->isAck[0];
2402 isAck = fdbk->isAck[2];
2406 /* M > 1 same below logic apply.
2407 If SPS occasion and rel pdcch is present
2408 SPS occasion after SPS release cannot
2413 isAck = fdbk->isAck[itr];
2416 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2418 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2419 /* Remove release PDCCH from the subframe */
2420 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2421 sf->relPdcch = NULLP;
2431 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2432 /* Remove release PDCCH from the subframe */
2433 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2434 sf->relPdcch = NULLP;
2436 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2439 if ( found == FALSE )
2441 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2442 RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,"CRNTI:%d"
2443 " NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2444 ue->ueId,timeInfo.sfn, timeInfo.slot);
2445 err->errType = RGSCHERR_DHM_FDBK_IND;
2446 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2451 #endif /* LTEMAC_SPS */
2452 /* Initialise the Ack/Nack feedback */
2453 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2454 scheduling. So added a condition !isMsg4 to avoid calling the function
2455 rgSCHUtlInitUeANFdbkInfo*/
2456 if((ue) && (!anUpd) && (!isMsg4))
2459 /* TODO:: Initi the anInfo all the serving cells */
2460 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2462 if(ue->cellInfo[idx])
2464 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2465 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2466 * else don't do anything. basically continue for next serving
2470 rgSCHUtlInitUeANFdbkInfo(anInfo);
2475 rgSCHUtlInitUeANFdbkInfo(anInfo);
2481 //#endif /* LTEMAC_SPS */
2484 /** * @brief Handler for HARQ feedback received for DL transmission.
2488 * Function : rgSCHDhmPrcFdbkForTb
2490 * Process Hq Prc Fdbk for a TB
2492 * @param[in] RgSchCellCb *cell
2493 * @param[in] RgTfuHarqAckIndInfo *fdbk
2494 * @param[in] RgSchErrInfo *err
2499 S16 rgSCHDhmPrcFdbkForTb
2503 RgSchDlHqProcCb *hqP,
2508 CmLteTimingInfo timingInfo,
2510 RgInfRlsHqInfo *rlsHqBufs,
2515 Inst inst = cell->instIdx;
2517 #ifdef RGSCH_SPS_STATS
2518 RgSchCmnDlHqProc *cmnHqDl;
2521 RgSchRaCb *raCb = NULLP;
2523 Bool hqFreed =FALSE;
2524 Bool maxHqRetxReached = FALSE;
2525 RgSchCmnDlUe *ueDl = NULLP;
2526 RgSchCellCb *sCell = hqP->hqE->cell;
2528 RgSchEmtcDlSf *emtcSf;
2529 CmLteTimingInfo frm = timingInfo;
2534 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2537 /* Fix : syed MultiUe per TTI crash in TA List. */
2538 maxHqRetxReached = FALSE;
2540 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2541 * TODO: Need to enhance this in case of TM4 testing,
2542 * when cwSwap flag is considered. */
2544 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2545 tbCnt=%d , isAck=%d",tbCnt,isAck));
2546 if (isAck == TFU_HQFDB_ACK)
2548 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2550 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2551 /* Do not update the Ul Trans Time in case of raCb */
2554 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2556 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2562 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2563 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2568 else if (isAck == TFU_HQFDB_NACK)
2570 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2571 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2572 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2573 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2574 /* Do not update the Ul Trans Time in case of raCb */
2577 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2578 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2580 sCell->tenbStats->sch.dlNack[tbCnt]\
2581 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2588 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2590 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2591 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2594 /* Added Dl TB count for NACKED data*/
2596 if(hqP->tbInfo[tbCnt].txCntr == 1)
2598 cell->dlUlTbCnt.tbTransDlFaulty++;
2604 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2605 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2606 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2609 sCell->tenbStats->sch.dlDtx[tbCnt]\
2610 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2613 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2618 /* Added Dl TB count for DTXED data*/
2620 if(hqP->tbInfo[tbCnt].txCntr == 1)
2622 cell->dlUlTbCnt.tbTransDlFaulty++;
2627 /* Check if this is repeating UE */
2628 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2630 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2637 /* For a Normal UE take the decision here */
2638 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2640 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2643 /* Process either the ACK received or max retries have occurred */
2644 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2645 if (TFU_HQFDB_ACK == isAck)
2649 /* SR_RACH_STATS : MSG4 ACK*/
2654 raCb = rgSCHDbmGetRaCb(cell, rnti);
2656 RGSCHDBGINFO(cell->instIdx,
2657 (rgSchPBuf(cell->instIdx), "Ack Rcvd. FdbkInd for Msg4Done\n"));
2658 /* Inform Random Access Module regarding the ack received */
2661 /*RRC Connection Setup failure issue where RRC connection
2662 * setup was not reaching UE due to message 4 HARQ failure */
2663 printf("\nMSG4 Ack ,calling rgSCHRamMsg4Done\n");
2664 ret = rgSCHRamMsg4Done(cell, raCb);
2669 printf("\nraCb is NULLP\n");
2672 else /*ccpu00114124- HARQ Release for Msg4 */
2674 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2675 /* Push this harq process back to the free queue */
2676 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2678 if(hqP->tbInfo[tbCnt].txCntr == 1)
2680 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2683 RGSCH_NULL_CHECK(cell->instIdx, ue);
2684 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2685 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2694 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2695 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2697 if(hqP->tbInfo[tbCnt].txCntr == 1)
2699 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2702 RGSCH_NULL_CHECK(cell->instIdx, ue);
2703 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2707 #ifdef XEON_SPECIFIC_CHANGES
2708 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2712 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2713 maxHqRetxReached = hqRls;
2719 /* MS_WORKAROUND: to increase Harq Fail Counter .
2720 The status field is required for tracking the number of harq faliures at MAC*/
2723 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2724 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2727 else if(maxHqRetxReached)
2729 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
2730 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2731 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
2736 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2737 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2739 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2740 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2741 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2745 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
2747 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
2750 } /* rgSCHDhmPrcFdbkForTb */
2751 /** * @brief Function to decode the position of HarqFb for eachCell.
2755 * Function : rgSchGetHqFdbkPos
2757 * @param[in] RgSchCellCb *cell,
2758 * @param[in] RgSchUeCb *ue,
2759 * @param[in] RgSchDlHqProcCb *hqP,
2760 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
2761 * @param[in] Bool *isAck,
2762 * @param[in] RgTfuHqInfo *fdbk,
2765 Void rgSchGetHqFdbkPos
2769 RgSchDlHqProcCb *hqP,
2770 RgrSchFrmt1b3TypEnum uciFrmtTyp,
2775 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2777 isAck[0] = fdbk->isAck[0];
2778 isAck[1] = fdbk->isAck[1];
2782 /* LAA Making all ack for LAA CELL */
2783 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
2793 /* PUSCH:: Fdbks are in the increasing order
2794 * of servCellIdx as per 36.212 section 5.2.26*/
2795 switch(ue->f1bCsAVal)
2797 case RG_SCH_A_VAL_2:
2799 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2801 isAck[0] = fdbk->isAck[1];/*SCell*/
2802 isAck[1] = fdbk->isAck[1];/*SCell*/
2806 isAck[0] = fdbk->isAck[0];/*PCell*/
2807 isAck[1] = fdbk->isAck[0];/*PCell*/
2811 case RG_SCH_A_VAL_3:
2813 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2816 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
2817 hqP->hqE->cell->cellId,
2820 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
2822 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
2824 { /* Sec cell is in mimo mode */
2825 /* use 0 and 1 for sec in case of pucch
2826 * and 1 and 2 in case of PUSCH as the primary cell is in
2827 * siso case as A =3 */
2830 isAck[0] = fdbk->isAck[0];
2831 isAck[1] = fdbk->isAck[1];
2833 {/* PUSCH as per 36.212 serction 5.2.26*/
2834 isAck[0] = fdbk->isAck[1];
2835 isAck[1] = fdbk->isAck[2];
2838 {/* sec cell is in siso */
2839 isAck[0] = fdbk->isAck[2];
2843 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2844 {/* primay cell is in mimo
2846 isAck[0] = fdbk->isAck[0];
2847 isAck[1] = fdbk->isAck[1];
2852 isAck[0] = fdbk->isAck[2];
2854 {/* PUSCH as per 36.212 serction 5.2.26*/
2855 isAck[0] = fdbk->isAck[0];
2861 case RG_SCH_A_VAL_4:
2863 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2865 isAck[0] = fdbk->isAck[2];
2866 isAck[1] = fdbk->isAck[3];
2869 if(isAck[0] == TFU_HQFDB_ACK)
2871 gSCellTb1AckCount++;
2872 }else if(isAck[0] == TFU_HQFDB_NACK)
2874 gSCellTb1NackCount++;
2877 gSCellTb1DtxCount++;
2880 if(isAck[1] == TFU_HQFDB_ACK)
2882 gSCellTb2AckCount++;
2883 }else if(isAck[1] == TFU_HQFDB_NACK)
2885 gSCellTb2NackCount++;
2888 gSCellTb2DtxCount++;
2896 isAck[0] = fdbk->isAck[0];
2897 isAck[1] = fdbk->isAck[1];
2900 if(isAck[0] == TFU_HQFDB_ACK)
2902 gPCellTb1AckCount++;
2903 }else if(isAck[0] == TFU_HQFDB_NACK)
2905 gPCellTb1NackCount++;
2908 gPCellTb1DtxCount++;
2911 if(isAck[1] == TFU_HQFDB_ACK)
2913 gPCellTb2AckCount++;
2914 }else if(isAck[1] == TFU_HQFDB_NACK)
2916 gPCellTb2NackCount++;
2919 gPCellTb2DtxCount++;
2934 }/* End of rgSchGetHqFdbkPos */
2936 Void rgSchGetHqFdbkPosFormat3
2938 RgSchDlHqProcCb *hqP,
2943 uint8_t cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
2944 isAck[0] = (uint8_t)fdbk[cellIdx];
2945 isAck[1] = (uint8_t)fdbk[cellIdx + 1];
2948 /** * @brief Handler for HARQ feedback received for DL transmission.
2952 * Function : rgSCHDhm5gtfHqFdbkInd
2954 * This function shall act on the feedback received from TOM for DL
2955 * transmission. If the feedback for msg4 is final (after max transmissions
2956 * or ACK) inform RAM that Msg4 transmission is done.
2959 * @param[in] Void *cb
2960 * @param[in] uint8_t cbType
2961 * @param[in] RgSchCellCb *cell
2962 * @param[in] RgTfuHarqAckIndInfo *fdbk
2963 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2964 * @param[in] RgSchErrInfo *err
2969 S16 rgSCHDhm5gtfHqFdbkInd
2973 CmLteTimingInfo timingInfo,
2978 RgSchDlHqProcCb *hqP = NULLP;
2979 CmLList *node = NULLP;
2983 Bool isMsg4 = FALSE;
2986 uint8_t hqPCount = 0;
2987 RgInfRlsHqInfo *rlsHqBufs = NULLP;
2989 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
2991 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
2993 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
2995 hqPCount = lnk->count;
3000 hqP = (RgSchDlHqProcCb *)node->node;
3002 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3003 procId = hqP->procId;
3005 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3007 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
3009 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
3010 timingInfo, fdbk, rlsHqBufs, err);
3012 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3014 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3015 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3017 rlsHqBufs->numUes++;
3023 } /* rgSCHDhm5gtfHqFdbkInd */
3025 /** * @brief Handler for HARQ feedback received for DL transmission.
3029 * Function : rgSCHDhmHqFdbkInd
3031 * This function shall act on the feedback received from TOM for DL
3032 * transmission. If the feedback for msg4 is final (after max transmissions
3033 * or ACK) inform RAM that Msg4 transmission is done.
3036 * @param[in] Void *cb
3037 * @param[in] uint8_t cbType
3038 * @param[in] RgSchCellCb *cell
3039 * @param[in] RgTfuHarqAckIndInfo *fdbk
3040 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3041 * @param[in] RgSchErrInfo *err
3046 S16 rgSCHDhmHqFdbkInd
3051 CmLteTimingInfo timingInfo,
3053 RgInfRlsHqInfo *rlsHqBufs,
3057 RgSchDlHqTbCb *tbCb;
3058 RgSchDlHqEnt *hqE = NULLP;
3059 RgSchDlHqProcCb *hqP = NULLP;
3060 CmLList *node = NULLP;
3062 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3063 RgSchUeCb *ue = NULLP;
3067 Bool isMsg4 = FALSE;
3068 RgSchRaCb *raCb = NULLP;
3070 /* Added Insure Fixes Of UR.Initialized procId */
3072 /* DTX Change: Bool is converted into uint8_t*/
3073 uint8_t isAck[2]={0}; /*Changed to Array of 2*/
3075 uint8_t hqPCount = 0;
3078 CmLteTimingInfo fdbkRcptTime = timingInfo;
3079 #ifdef RGSCH_SPS_STATS
3080 RgSchCmnDlHqProc *cmnHqDl;
3084 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3086 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3088 /* Get the subframe associated with the feedback */
3089 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3090 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3091 * serving the purpose */
3092 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3094 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3095 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3097 raCb = (RgSchRaCb *)(cb);
3099 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3105 rnti = raCb->tmpCrnti;
3109 ue = (RgSchUeCb *)(cb);
3110 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3112 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3115 hqPCount = lnk->count;
3118 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3123 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3124 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3125 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3126 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3127 from get CQI from cmInfo->cqi
3128 from cmInfo get iTbs cmInfo->iTbs[0]
3129 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3130 Update stats in cellCb
3131 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3132 if (fdbk->isAck == TRUE)
3133 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3135 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3136 DL Ack/Nack statistics
3138 #ifdef MAC_SCH_STATS
3139 if (hqE->ue != NULLP)
3141 RgSchUeCb *ueCb = hqE->ue;
3142 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3143 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3144 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3145 static uint32_t retxCnt = 0;
3147 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3149 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3154 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3156 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3157 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3159 #endif /* MAC_SCH_STATS */
3161 /* Fetch the harqProc from the inUse list */
3163 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3164 /* Call Common module with the feedback information */
3165 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3167 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3169 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3172 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3173 {/* Feedback for SPS Release on PCell
3174 If Pcell is in mimo, feedback index will be 0
3176 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3178 isAck[0] = fdbk->isAck[0];
3181 isAck[0] = fdbk->isAck[2];
3184 /* Not releasing pdcch here
3185 * as it is already done at the time of
3187 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3194 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
3195 "CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3196 "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3201 isAck[0] = fdbk->isAck[0];
3202 /* Note: Since relPdcchFbkTimimg matches with the recieved
3203 * feedback, assumed that feedback is for release PDCCH */
3204 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3206 /* Remove release PDCCH from the subframe */
3207 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3208 sf->relPdcch = NULLP;
3213 #endif /* LTEMAC_SPS */
3215 /* Remove the harq process from the subframe */
3216 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3217 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3230 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3232 hqP = (RgSchDlHqProcCb *)node->node;
3234 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3236 procId = hqP->procId;
3238 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3240 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3241 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3243 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3245 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3250 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3252 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3254 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3256 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3257 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3260 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3262 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3263 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3265 rlsHqBufs->numUes++;
3270 node = sf->ackNakRepQ.first;
3273 tbCb = (RgSchDlHqTbCb *)(node->node);
3276 procId = hqP->procId;
3277 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3278 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3279 if (HQ_TB_WAITING == tbCb->state)
3281 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3282 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3283 timingInfo, isAck[0], rlsHqBufs, err);
3285 hqP->cwSwpEnabled = FALSE;
3286 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3288 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3289 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3291 rlsHqBufs->numUes++;
3298 } /* rgSCHDhmHqFdbkInd */
3299 #endif /* LTE_FDD */
3303 * @brief Handler for Harq related UE configuration.
3307 * Function : rgSCHDhmRgrUeCfg
3309 * This function shall fetch the harq related information into the
3310 * respective ueCb from the UE configuration as provided by the
3313 * @param[in] RgSchCellCb *cell
3314 * @param[in] RgSchUeCb *ueCb
3315 * @param[in] RgrUeCfg *ueCfg
3316 * @param[out] RgSchErrInfo *err
3321 Void rgSCHDhmRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ueCb,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3326 /* Initialize the TA Timer */
3327 cmInitTimers(&ueCb->taTmr, 1);
3329 /* Setting these values irrespective of taTmr value */
3330 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3331 /* Corrected default value of TA as per 36.213, 4.2.3 */
3332 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3334 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3335 ueCb->dl.taCb.outStndngTa = FALSE;
3336 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3338 /* Start TA timer only if cfgd as FINITE value */
3339 if (ueCfg->ueTaTmrCfg.pres)
3341 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3342 * TA command before the expiry of TA at UE. Also considering for
3343 * possible retx for this TA command */
3344 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3345 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3347 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3349 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3352 } /* rgSCHDhmRgrUeCfg */
3356 * @brief Handler for HARQ related UE Reconfiguration
3360 * Function : rgSCHDhmRgrCellCfg
3362 * This function shall fetch the HARQ related information into the
3363 * respective ueCb from the UE configuration as provided by the
3366 * @param[in] RgSchCellCb *cell
3367 * @param[in] RgrCellCfg *cellCfg
3368 * @param[out] RgSchErrInfo *err
3374 Void rgSCHDhmRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3377 PTR pUeCb;/* previous UE Control block */
3378 PTR nUeCb;/* next UE control block */
3386 cell->dlHqCfg = cellCfg->dlHqCfg;
3389 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3397 /* Update the DL Harq related information */
3398 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3399 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3402 /* Initializing the list for ueCbs that would have ta */
3403 cmLListInit(&cell->taUeLst);
3405 cmLListInit(&cell->ccchSduUeLst);
3406 cmLListInit(&cell->contResGrdTmrLst);
3407 cmLListInit(&cell->contResTmrLst);
3409 if(cell->emtcEnable)
3411 rgSCHDhmEmtcRgrCellCfg(cell);
3416 /* Initializing the timer queue */
3417 cell->tqCp.nxtEnt = 0;
3418 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3420 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3422 cell->tq[idx].first = NULLP;
3423 cell->tq[idx].tail = NULLP;
3426 } /* rgSCHDhmRgrCellCfg */
3429 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3433 * Function : rgSCHDhmRgrCellRecfg
3435 * This function shall fetch the HARQ related information into the
3436 * respective ueCb from the UE configuration as provided by the
3439 * @param[in] RgSchCellCb *cell
3440 * @param[in] RgrCellRecfg *cellRecfg
3441 * @param[out] RgSchErrInfo *err
3447 Void rgSCHDhmRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *cellRecfg,RgSchErrInfo *err)
3450 PTR pUeCb;/* previous UE Control block */
3451 PTR nUeCb;/* next UE control block */
3458 /* Update the cell with recieved configuration */
3459 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3461 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3465 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3473 /* Update the DL Harq related information */
3474 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3475 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3480 } /* rgSCHDhmRgrCellRecfg */
3483 * @brief Handler for freeing up the HARQ related information from ueCb
3487 * Function : rgSCHDhmFreeUe
3489 * This function shall free up the HARQ specific information from ueCb.
3491 * @param[in] RgSchUeCb *ueCb
3496 Void rgSCHDhmFreeUe(RgSchUeCb *ueCb)
3499 /* If TA Timer is running. Stop it */
3500 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3502 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3505 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3506 * doesn't expire after UE is deleted */
3508 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3510 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3512 #endif /* ifdef RGR_V1*/
3515 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3517 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3520 /* This UE needs to be removed from its entry into cell's taUeLst */
3521 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3522 if(ueCb->taLnk.node)
3524 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3525 ueCb->taLnk.node = NULLP;
3528 if (ueCb->dlTaLnk.node != NULLP)
3530 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3531 * function directly from other modules. APIs should be defined and/or used
3532 * instead. Please check for other possible incorrect usage. */
3533 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3538 } /* rgSCHDhmFreeUe */
3541 * @brief Handler for updating the TA.
3545 * Function : rgSCHDhmUpdTa
3547 * This function shall update the TA received.
3549 * @param[in] RgSchCellCb *cell
3550 * @param[in] RgSchUeCb *ueCb
3551 * @param[in] uint8_t ta
3556 Void rgSCHDhmUpdTa(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t ta)
3559 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3561 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3562 ueCb->dl.taCb.numRemSf = 2;
3563 rgSCHUtlDlTARpt(cell, ueCb);
3564 /* If TA Timer is running. Stop it */
3565 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3567 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3570 /* SR_RACH_STATS : TA MODIFIED */
3571 if (ueCb->dl.taCb.ta != ta)
3575 ueCb->dl.taCb.ta = ta;
3579 /* [ccpu00121813]-ADD-Updating outstanding values
3580 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3581 * has been scheduled,further TA values get stored in outstndngTaval.
3582 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3583 * then schedule the outstanding TA val if present */
3584 ueCb->dl.taCb.outStndngTa = TRUE;
3585 ueCb->dl.taCb.outStndngTaval = ta;
3589 } /* rgSCHDhmUpdTa */
3591 /** @brief This function handles the TA timer expiry.
3595 * Function: This function handled the TA Expiry.
3601 * @param[in] RgSchUeCb *ueCb
3606 Void rgSCHDhmProcTAExp( RgSchUeCb *ueCb)
3608 /* Ask scheduler to schedule this UE */
3609 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3610 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
3612 } /* end of rgSCHDhmProcTAExp */
3614 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
3616 * @brief Handler for Adding scheduled logical channel data information
3621 * Function : rgSCHDhmAddLcData
3623 * This function shall add the scheduled logical channel data
3624 * information to the HARQ process.
3626 * @param[in] RgSchLchAllocInfo *lchData
3627 * @param[in] RgSchDlHqTbCb *tbInfo
3632 S16 rgSCHDhmAddLcData(Inst inst,RgSchLchAllocInfo *lchData,RgSchDlHqTbCb *tbInfo)
3635 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
3640 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
3646 } /* rgSCHDhmAddLcData */
3650 * @brief Handler for releaseing the subframe allocation.
3654 * Function : rgSCHDhmTddRlsSubFrm
3656 * This function shall be invoked to release the DL Sf
3657 * allocations for which HARQ feedback time has expired.
3659 * @param[in] RgSchCellCb *cellCb
3660 * @param[in] CmLteTimingInfo uciTimingInfo;
3665 S16 rgSCHDhmTddRlsSubFrm(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3667 CmLteTimingInfo dlSfTime;
3668 RgSchTddDlAscSetIdxK ascIdx;
3673 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3674 noFdbks = ascIdx.numFdbkSubfrms;
3675 for(i=0; i < noFdbks; i++)
3677 /* Get the subframe and sfn for which HARQ Ack/Nack
3679 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3680 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3681 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3682 * as it is serving the purpose */
3683 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3684 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
3687 }/* rgSCHDhmTddRlsSubFrm */
3690 uint32_t macDtx = 0;
3693 * @brief Handler for Removing the HARQ process from a dlsf.
3697 * Function : rgSCHDhmRlsDlsfHqProc
3699 * This function shall be invoked for every tti. It goes back to
3700 * to the sixth last subframe to check whether it still exists. If
3701 * that exists this function traverses through the entire harq
3702 * proc list associated and frees up all of them.
3704 * @param[in] RgSchCellCb *cellCb
3705 * @param[in] CmLteTimingInfo timingInfo
3710 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3713 CmLteTimingInfo dlSfTime;
3714 CmLteTimingInfo nxtfrm = {0,0};
3715 RgSchDlHqProcCb *tmpHqProc;
3716 RgSchTddDlAscSetIdxK ascIdx;
3719 RgSchDlSf *nxtDlsf = NULLP;
3723 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
3724 uint8_t maxRetx=FALSE;
3725 RgSchTddANInfo *anInfo = NULLP;
3726 RgSchDlHqTbCb *tbCb;
3727 RgSchUeCb *ue = NULLP;
3730 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3731 noFdbks = ascIdx.numFdbkSubfrms;
3732 for(i=0; i < noFdbks; i++)
3734 /* Get the subframe and sfn for which HARQ Ack/Nack
3736 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3737 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3738 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3739 * as it is serving the purpose */
3740 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3742 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
3743 if(cellCb->ulDlCfgIdx != 5)
3745 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
3747 /* Subframe is present. Delete all the harq associations from
3751 /*Handling for Msg4*/
3752 node = dlSf->msg4HqPLst.first;
3755 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
3757 tmpHqProc->cwSwpEnabled = FALSE;
3758 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
3760 tbCb = &tmpHqProc->tbInfo[0];
3762 /* Fix : syed MultiUe per TTI crash in TA List. */
3766 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3769 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3771 /* Delete the Harq Association. Release the Harq Process */
3772 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3774 if (tbCb->taSnt == TRUE)
3776 /* [ccpu00127148] Correcting the check */
3777 if (TRUE == maxRetx)
3779 tbCb->taSnt = FALSE;
3780 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3781 ue->dl.taCb.state = RGSCH_TA_IDLE;
3783 rgSCHUtlReTxTa(cellCb, ue);
3789 node = dlSf->ueLst.first;
3795 ue = (RgSchUeCb *)(node->node);
3799 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
3802 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
3803 hqPNode = hqPNode->next;
3804 for (idx = 0 ;idx < 2; idx++)
3806 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
3808 tbCb = &tmpHqProc->tbInfo[idx];
3810 /* Fix : syed MultiUe per TTI crash in TA List. */
3814 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3817 /* Update feedback time for this process so that
3818 * next subframe its picked up */
3820 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3821 tmpHqProc->hqE->cell->instIdx,
3822 tmpHqProc->hqE->cell->cellId,
3824 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3826 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
3830 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
3831 "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX"
3832 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
3833 uciTimingInfo.slot));
3835 else if (tbCb->fbkRepCntr == 0)
3837 /* Initialise the Ack/Nack feedback */
3839 if(!(anInfo->dlDai))
3841 rgSCHUtlInitUeANFdbkInfo(anInfo);
3846 /* Update feedback time for this process so that
3847 * * next subframe its picked up */
3848 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3849 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3850 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3851 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
3856 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3857 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
3860 /* Delete the Harq Association. Release the Harq Process */
3861 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3863 if (tbCb->taSnt == TRUE)
3865 /* [ccpu00127148] Correcting the check */
3866 if (TRUE == maxRetx)
3868 tbCb->taSnt = FALSE;
3869 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3870 ue->dl.taCb.state = RGSCH_TA_IDLE;
3872 rgSCHUtlReTxTa(cellCb, ue);
3874 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
3875 "Nack/DTX Rcvd for TA. Max Tries Attempted");
3884 node = dlSf->ackNakRepQ.first;
3887 tbCb = (RgSchDlHqTbCb *)(node->node);
3888 tmpHqProc = tbCb->hqP;
3889 /* [ccpu00121813]-ADD-Fetch ueCb */
3890 ue = tmpHqProc->hqE->ue;
3891 /* Fix : syed MultiUe per TTI crash in TA List. */
3896 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
3897 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
3901 /* If This is not the last repetition */
3902 if (tbCb->fbkRepCntr > 1)
3904 /* Update feedback time for this process so that
3905 * next subframe its picked up */
3907 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3908 tmpHqProc->hqE->cell->instIdx,
3909 tmpHqProc->hqE->cell->cellId,
3911 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3913 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
3919 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3920 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3921 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3922 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3928 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3930 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
3932 /*even if one NACK, we consider the feedback
3933 * on a whole as NACk */
3934 if ( tbCb->nackCount != 0 )
3936 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
3940 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3944 /* Delete the Harq Association. Release the Harq Process */
3945 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3947 }/*if(((tbCb->nackCount+....*/
3950 if (tbCb->taSnt == TRUE)
3952 /* [ccpu00127148] Correcting the check */
3953 if (TRUE == maxRetx)
3955 tbCb->taSnt = FALSE;
3956 ue->dl.taCb.state = RGSCH_TA_IDLE;
3958 rgSCHUtlReTxTa(cellCb, ue);
3959 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
3960 "Nack/DTX Rcvd for TA. Max Tries Attempted");
3967 }/* rgSCHDhmRlsDlsfHqProc */
3968 #else /* ifdef LTE_TDD */
3970 * @brief Handler for Removing the HARQ process from a dlsf.
3974 * Function : rgSCHDhmRlsDlsfHqProc
3976 * This function shall be invoked for every tti. It goes back to
3977 * to the sixth last subframe to check whether it still exists. If
3978 * that exists this function traverses through the entire harq
3979 * proc list associated and frees up all of them.
3981 * @param[in] RgSchCellCb *cell
3986 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cell,CmLteTimingInfo timingInfo)
3989 CmLteTimingInfo frm;
3990 RgSchDlHqProcCb *tmpHqProc;
3995 RgSchDlHqTbCb *tbCb;
3998 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
3999 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4000 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4001 * as it is serving the purpose */
4002 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
4005 /* Get the required Last subframe */
4006 sf = rgSCHUtlSubFrmGet(cell, frm);
4009 /*Handling for Msg4*/
4010 node = sf->msg4HqPLst.first;
4013 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4014 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4016 tbCb = &tmpHqProc->tbInfo[0];
4017 /* Fix : syed MultiUe per TTI crash in TA List. */
4020 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4021 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4024 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4025 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4027 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4032 if (tbCb->fbkRepCntr != 0)
4034 /* Update timingInfo for this hqP so that next subframe its picked up */
4035 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4036 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4040 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4042 /* Delete the Harq Association. Release the Harq Process */
4043 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4047 /* Subframe is present. Delete all the harq associations from
4050 node = sf->ueLst.first;
4053 ue = (RgSchUeCb *)(node->node);
4057 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4061 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4062 tmpHqProc->cwSwpEnabled = FALSE;
4063 hqPNode = hqPNode->next;
4064 for (idx = 0 ;idx < 2; idx++)
4066 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4068 tbCb = &tmpHqProc->tbInfo[idx];
4069 /* Fix : syed MultiUe per TTI crash in TA List. */
4072 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4073 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4076 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4077 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4079 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4084 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4087 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4090 /* Delete the Harq Association. Release the Harq Process */
4091 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4093 if (tbCb->taSnt == TRUE)
4095 /* [ccpu00127148] Correcting the check */
4096 if (TRUE == maxRetx)
4098 tbCb->taSnt = FALSE;
4099 ue->dl.taCb.state = RGSCH_TA_IDLE;
4101 rgSCHUtlReTxTa(cell, ue);
4102 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4103 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4106 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4107 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4116 } /* rgSCHDhmRlsDlsfHqProc */
4121 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4126 * Function: rgSCHDhmMarkSpsHqProc
4127 * Purpose: This function returns the HARQ process with the given ID.
4128 * Invoked by: SPS Module
4130 * - Get the HARQ process by index from the UE
4131 * - Set isSpsHqProc = TRUE
4133 * @param[in] RgSchUeCb *ue
4134 * @param[in] uint8_t idx
4136 * -# ROK if successful
4137 * -# RFAILED otherwise
4140 S16 rgSCHDhmMarkSpsHqProc(RgSchUeCb *ue,uint8_t idx)
4142 RgSchDlHqProcCb *hqP;
4144 /* Pick the proc based on the index provided */
4145 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4148 } /* rgSCHDhmMarkSpsHqProc */
4149 #endif /* RG_UNUSED */
4150 #endif /* LTEMAC_SPS */
4153 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4157 * Function : rgSCHDhmProcHqFdbkAckNackRep
4159 * This function shall act on the feedback received from TOM for DL
4163 * @param[in] RgSchDlHqProcCb *hqP
4164 * @param[in] RgSchDlSf *sf
4165 * @param[in] uint8_t tbCnt
4166 * @param[in] uint8_t *isAck
4171 static S16 rgSCHDhmProcHqFdbkAckNackRep(RgSchDlHqProcCb *hqP,RgSchDlSf *sf,uint8_t tbCnt,uint8_t *isAck)
4173 /* Check if this is repeating UE */
4174 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4175 /* Check if last repetition */
4176 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4178 /* Update timingInfo for this hqP so that next subframe its picked up */
4179 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4180 hqP->tbInfo[tbCnt].timingInfo, 1);
4184 /* Take decision here based on the number
4185 * of DTX's,NACK's and ACK's received
4187 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4188 (hqP->tbInfo[tbCnt].dtxCount)))
4190 *isAck = TFU_HQFDB_ACK;
4192 /*even a single NACK indicates that UE received
4195 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4197 *isAck = TFU_HQFDB_NACK;
4201 *isAck = TFU_HQFDB_DTX;
4205 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4208 #endif /* ifndef LTE_TDD */
4211 /* Freeing up the HARQ proc blocked for
4212 * indefinite time in case of Retx */
4214 * @brief This function handles the scenario in case Retx allocation is failed.
4218 * Function: rgSCHDhmDlRetxAllocFail
4221 * @param[in] RgSchUeCb *ue
4222 * @param[in] RgSchDlHqProcCb *hqP
4226 S16 rgSCHDhmDlRetxAllocFail(RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
4229 RgInfRlsHqInfo *rlsHqInfo;
4231 Bool maxRetx = FALSE;
4232 RgSchCmnCell *cellSch;
4234 cell = hqP->hqE->cell;
4235 cellSch = RG_SCH_CMN_GET_CELL(cell);
4236 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4238 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4239 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4241 hqP->tbInfo[0].cntrRetxAllocFail++;
4244 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4245 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4247 hqP->tbInfo[1].cntrRetxAllocFail++;
4250 /* initialize MAC-SCH interface HARQ release info */
4251 rlsHqInfo->numUes = 0;
4252 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4254 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4255 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4257 if (hqP->hqE->msg4Proc == hqP)
4259 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4263 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4266 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4271 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4272 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4276 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4277 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4280 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4281 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4284 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4285 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4286 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4289 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4290 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4292 if (hqP->hqE->msg4Proc == hqP)
4294 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4298 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4301 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4303 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4304 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4305 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4306 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4307 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4310 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4312 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4313 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4315 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4318 /* send HARQ release to MAC */
4319 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4321 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4322 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4323 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4324 rlsHqInfo->numUes = 1;
4326 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4327 RgSchMacRlsHq(&pst, rlsHqInfo);
4334 static S16 rgSCHDhmUpdateAckNackHistory(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t hqfdbk,uint8_t tbCnt)
4338 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4341 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4344 if (hqfdbk == TFU_HQFDB_ACK)
4346 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4350 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4353 printf("deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4354 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4355 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4358 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4363 S16 rgSCHDhmUpdBlerBasediTbsEff(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t tbCnt)
4367 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4368 uint8_t cfi = cellSch->dl.currCfi;
4369 uint8_t maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4370 maxiTbs = RG_SCH_DL_MAX_ITBS;
4372 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4373 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4377 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4378 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4382 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4383 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4387 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4388 ueDl->laCb[tbCnt].deltaiTbs)/100),
4389 ueCb->cell->thresholds.maxDlItbs);
4392 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4394 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4396 /* Eff for CW for 1 Layer Tx */
4397 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4398 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4399 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4401 /* Eff for CW for 2 Layer Tx */
4402 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4403 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4404 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4412 * @brief This function Processes the Hq Fdbk in case of
4413 * special Bundling in TDD (FAPIv1.1: Table 79)
4417 * Function: rgSCHDhmPrcSplBundlFdbk
4418 * Purpose: To Interpret the Harq Feedback according to
4419 * table 7.3-1: 36.213
4421 * 0 = 0 or None (UE detect at least one DL is missed)
4422 * 1 = 1 or 4 or 7 ACKs reported
4423 * 2 = 2 or 5 or 8 ACKs reported
4424 * 3 = 3 or 6 or 9 ACKs reported
4425 * 4 = DTX (UE did not transmit anything)
4427 * @param[in] TfuHqInfo *fdbk
4428 * @param[in] uint8_t hqCnt
4432 static Void rgSCHDhmPrcSplBundlFdbk(RgSchCellCb *cell,TfuHqInfo *fdbk,uint8_t hqCnt)
4436 /* Num of ACKs reported by UE */
4437 numOfAcks = fdbk->isAck[0];
4439 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4440 fdbk->isAck[0] == TFU_HQFDB_DTX)
4446 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4447 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4449 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4452 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4453 the PDSCH trasnmission (spatial bundling). So we have
4454 to assume same feedback for both codewords */
4456 for(uint8_t idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4458 fdbk->isAck[idx] = fdbk->isAck[0];
4461 fdbk->isAck[1] = fdbk->isAck[0];
4469 * @brief This function adds HARQ process to FREE list
4473 * Function: rgSCHDhmHqPAdd2FreeLst
4476 * Invoked by: scheduler
4478 * @param[out] RgDlHqProc *hqP
4482 Void rgSCHDhmHqPAdd2FreeLst(RgSchDlHqProcCb *hqP)
4489 printf("Crashing already part of free lst\n");
4490 printf("Crashing %d \n", *p);
4494 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
4495 hqP->hqPLst = &hqP->hqE->free;
4499 if (hqP->hqE->free.count > 8)
4502 printf("Crashing invalid hq count\n");
4503 printf("Crashing %d \n", *p);
4509 rgSCHLaaHndlHqProcFree(hqP);
4513 } /* rgSCHDhmHqPAdd2FreeLst */
4517 * @brief This function adds HARQ process to inUse list
4521 * Function: rgSCHDhmHqPAdd2InUseLst
4524 * Invoked by: scheduler
4526 * @param[out] RgDlHqProc *hqP
4530 Void rgSCHDhmHqPAdd2InUseLst(RgSchDlHqProcCb *hqP)
4537 printf("Crashing already part of inuse lst\n");
4538 printf("Crashing %d \n", *p);
4542 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
4543 hqP->hqPLst = &hqP->hqE->inUse;
4547 if (hqP->hqE->inUse.count > 8)
4550 printf("Crashing invalid hq count \n");
4551 printf("Crashing %d \n", *p);
4557 } /* rgSCHDhmHqPAdd2InUseLst */
4560 * @brief This function adds HARQ process to FREE list
4564 * Function: rgSCHDhmHqPDelFrmFreeLst
4567 * Invoked by: scheduler
4569 * @param[out] RgDlHqProc *hqP
4573 Void rgSCHDhmHqPDelFrmFreeLst(RgSchDlHqProcCb *hqP)
4580 printf("Crashing not part of any lst\n");
4581 printf("Crashing %d \n", *p);
4586 if (hqP->hqPLst != &hqP->hqE->free)
4589 printf("Crashing del from wrong lst\n");
4590 printf("Crashing %d \n", *p);
4595 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
4596 hqP->hqPLst = NULLP;
4599 if (hqP->hqE->free.count > 8)
4602 printf("Crashing invalid hq count\n");
4603 printf("Crashing %d \n", *p);
4609 } /* rgSCHDhmHqPDelFrmFreeLst */
4614 * @brief This function adds HARQ process to FREE list
4618 * Function: rgSCHDhmHqPDelFrmInUseLst
4621 * Invoked by: scheduler
4623 * @param[out] RgDlHqProc *hqP
4627 Void rgSCHDhmHqPDelFrmInUseLst(RgSchDlHqProcCb *hqP)
4634 printf("Crashing not part of any lst\n");
4635 printf("Crashing %d \n", *p);
4641 if (hqP->hqPLst != &hqP->hqE->inUse)
4644 printf("Crashing del from wrong lst\n");
4645 printf("Crashing %d \n", *p);
4650 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
4651 hqP->hqPLst = NULLP;
4654 if (hqP->hqE->inUse.count > 8)
4657 printf("Crashing invalid hq count\n");
4658 printf("Crashing %d \n", *p);
4664 } /* rgSCHDhmHqPDelFrmInUseLst */
4667 /**********************************************************************
4670 **********************************************************************/