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*/
207 Void rgSCHDhmHqEntReset
212 Void rgSCHDhmHqEntReset(hqE)
216 RgSchDlHqProcCb *hqP;
218 cmLListInit(&hqE->inUse);
219 cmLListInit(&hqE->free);
220 for (i=0; i < hqE->numHqPrcs; i++)
222 hqP = &hqE->procs[i];
225 /* Fix - reset numLch */
226 hqP->tbInfo[0].numLch = 0;
227 hqP->tbInfo[1].numLch = 0;
228 hqP->tbInfo[0].txCntr = 0;
229 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
230 hqP->tbInfo[1].txCntr = 0;
231 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
232 hqP->tbInfo[0].tbIdx = 0;
233 hqP->tbInfo[1].tbIdx = 1;
234 hqP->tbInfo[0].hqP = hqP;
235 hqP->tbInfo[1].hqP = hqP;
236 hqP->tbInfo[0].state = HQ_TB_ACKED;
237 hqP->tbInfo[1].state = HQ_TB_ACKED;
238 hqP->tbInfo[0].contResCe = NOTPRSNT;
239 hqP->tbInfo[1].contResCe = NOTPRSNT;
240 hqP->lnk.node = (PTR)hqP;
241 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
243 rgSCHDhmHqPAdd2FreeLst(hqP);
244 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
245 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
246 hqP->drxCb.rttIndx = DRX_INVALID;
247 hqP->drxCb.reTxIndx = DRX_INVALID;
248 hqP->tbInfo[0].cntrRetxAllocFail = 0;
249 hqP->tbInfo[1].cntrRetxAllocFail = 0;
250 hqP->hasDcch = FALSE;
251 hqP->cwSwpEnabled = FALSE;
256 rgSCHLaaResetDlHqProcCb(hqP);
260 } /* rgSCHDhmHqEntReset */
263 * @brief This function assigns dlHqEnt of raCb to ueCb.
267 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
268 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
270 * Invoked by: configuration module
272 * @param[in] RgSchUeCb *ue
273 * @param[in] RgSchRaCb *raCb
278 Void rgSCHDhmAssgnUeHqEntFrmRaCb
284 Void rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb)
290 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
291 ue->cellInfo[0]->hqEnt->ue = ue;
292 /* Update the DL Harq related information */
293 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
295 /* Fix : set UE active in DL as UE initialization completed */
296 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
297 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
298 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
304 * @brief This function deletes the dlHqEnt.
308 * Function: rgSCHDhmDelHqEnt
309 * Purpose: This function deletes the dlHqEnt.
311 * Invoked by: configuration module
313 * @param[in] RgSchCellCb *cell
314 * @param[in] RgSchDlHqEnt **hqE
319 Void rgSCHDhmDelHqEnt
325 Void rgSCHDhmDelHqEnt(cell, hqE)
336 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
338 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
339 sizeof(RgSchDlHqEnt));
345 RgSchDlHqEnt *rgSCHDhmHqEntInit
350 RgSchDlHqEnt *rgSCHDhmHqEntInit(cell)
355 Inst inst = cell->instIdx;
357 /* Init the HARQ data structure */
358 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
360 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
361 "rgSCHDhmHqEntInit hqE alloc fail");
365 /* Init the HARQ processes */
366 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
367 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
368 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
370 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
371 "rgSCHDhmHqEntInit hqP alloc fail in hqE");
375 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
379 rgSCHLaaInitDlHqProcCb (cell, hqE);
382 /* Initialize maximum tranmission counter */
383 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
386 /* MW_WORKAROUND for ccpu00122893 */
387 rgSCHDhmHqEntReset(hqE);
393 } /* rgSCHDhmHqEntInit */
396 * @brief This function gets an available HARQ process.
400 * Function: rgSCHDhmGetAvlHqProc
401 * Purpose: This function returns an available HARQ process in
402 * the DL direction. All HARQ processes are maintained
403 * in queues of free and inuse.
405 * 1. Check if the free queue is empty. If yes, return
407 * 2. If not empty, update the proc variable with the
408 * first process in the queue. Return ROK.
410 * Invoked by: scheduler
412 * @param[in] RgSchUeCb *ue
413 * @param[in] CmLteTimingInfo timingInfo
414 * @param[out] RgSchDlHqProc **hqP
416 * -#ROK if successful
417 * -#RFAILED otherwise
421 S16 rgSCHDhmGetAvlHqProc
425 CmLteTimingInfo timingInfo,
426 RgSchDlHqProcCb **hqP
429 S16 rgSCHDhmGetAvlHqProc (cell, ue, timingInfo, hqP)
432 CmLteTimingInfo timingInfo;
433 RgSchDlHqProcCb **hqP;
436 RgSchDlHqEnt *hqE = NULLP;
437 RgSchDlHqProcCb *tmpHqProc;
440 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
444 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDhmGetAvlHqProc hqE NULL ue %d"
450 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
454 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
455 "rgSCHDhmGetAvlHqProc free %ld inUse %ld ue %d"
456 , hqE->free.count, hqE->inUse.count, ue->ueId);
457 /* No Harq Process available in the free queue. */
461 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
464 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
466 if (ue->dl.isSpsHqPInUse)
468 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
470 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
475 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
479 /* No Harq Process available in the free queue. */
486 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
487 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
488 tmpHqProc->hasDcch = FALSE;
489 tmpHqProc->cwSwpEnabled = FALSE;
491 /* Remove the element from the free Queue */
492 //cmLListDelFrm(&hqE->free, tmp);
493 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
495 /* Add the element into the inUse Queue as well */
496 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
497 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
502 rgSCHLaaResetDlHqProcCb(tmpHqProc);
506 tmpHqProc->tbSizeAtEstimate[0] = 0;
507 tmpHqProc->tbSizeAtEstimate[1] = 0;
508 tmpHqProc->tbSizeAtFnlz[0] = 0;
509 tmpHqProc->tbSizeAtFnlz[1] = 0;
510 tmpHqProc->tbSizeOfMvdTb[0] = 0;
511 tmpHqProc->tbSizeOfMvdTb[1] = 0;
512 tmpHqProc->itbsAtEstimate[0] = 0;
513 tmpHqProc->itbsAtEstimate[1] = 0;
514 tmpHqProc->prbAtEstimate = 0;
517 } /* rgSCHDhmGetAvlHqProc */
521 * @brief This function adds HARQ process for a given TB in to
522 * the inuse queue upon retx.
526 * Function: rgSCHDhmHqTbRetx
527 * Purpose: This function handles when a HARQ process is scheduled
528 * for retransmission. It adds the HARQ procss to inuse
530 * 1. Check if this HqP is already added to the inUse
531 * queue as part of this function call for other
532 * TB's retransmission.
533 * 2. If already present in inUse Q then do not add.
535 * Invoked by: scheduler
537 * @param[in] RgSchDlHqEnt *hqE
538 * @param[in] CmLteTimingInfo timingInfo
539 * @param[out] RgDlHqProc *hqP
540 * @param[in] uint8_t tbIdx
545 Void rgSCHDhmHqTbRetx
548 CmLteTimingInfo timingInfo,
549 RgSchDlHqProcCb *hqP,
553 Void rgSCHDhmHqTbRetx(hqE, timingInfo, hqP, tbIdx)
555 CmLteTimingInfo timingInfo;
556 RgSchDlHqProcCb *hqP;
560 uint8_t othrTbIdx = tbIdx ^ 1;
562 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
564 if (hqE->msg4Proc == hqP)
568 /* fix for ccpu00118633 No Hq proc Avl end*/
570 /* Extra:check if Harq process is already linked to in-use
571 Queue by means of other TB handling. */
572 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
575 if (hqE->msg4Proc != hqP)
577 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
578 rgSCHDhmHqPAdd2InUseLst(hqP);
582 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
585 } /* rgSCHDhmHqTbRetx */
588 * @brief This function returns last scheduled HARQ process for
589 * a UE's HARQ entity.
593 * Function: rgSCHDhmLastSchedHqProc
594 * Purpose: This function returns the last (most recent)
595 * process in the inUse list, which corresponds
596 * to the last scheduled process. Returns NULLP
598 * The reason for introducing this is to have
599 * an ability to check if UE was scheduled
600 * in the current subframe (scheduling would
601 * have caused a proc to be added to the end
602 * of the list, and checking time (only subframe
603 * number probably works) would confirm this.
605 * Invoked by: scheduler
607 * @param[in] RgSchDlHqEnt *hqE
608 * @return RgSchDlHqProcCb *
612 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc
617 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(hqE)
621 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
622 * until RACH procedure is completed */
623 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
627 return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
628 } /* rgSCHDhmLastSchedHqProc */
632 * @brief This function gets an available HARQ process for MSG 4.
636 * Function: rgSCHDhmGetCcchSduHqProc
637 * Purpose: This function returns an available HARQ process in
638 * the DL direction. All HARQ processes are maintained
639 * in queues of free and inuse.
641 * 1. Check if the free queue is empty. If yes, return
643 * 2. If not empty, update the proc variable with the
644 * first process in the queue. Return ROK.
646 * Invoked by: scheduler
648 * @param[in] RgSchRaCb *raCb
649 * @param[in] CmLteTimingInfo timingInfo
650 * @param[out] RgSchDlHqProcCb **hqP
652 * -#ROK if successful
653 * -#RFAILED otherwise
657 S16 rgSCHDhmGetCcchSduHqProc
660 CmLteTimingInfo timingInfo,
661 RgSchDlHqProcCb **hqP
664 S16 rgSCHDhmGetCcchSduHqProc (ueCb, timingInfo, hqP)
666 CmLteTimingInfo timingInfo;
667 RgSchDlHqProcCb **hqP;
670 RgSchDlHqProcCb *tmpHqProc;
674 hqE = ueCb->cellInfo[0]->hqEnt;
675 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
678 /* No Harq Process available in the free queue. */
682 /* Remove the element from the free Queue and */
683 /* set the MSG 4 HARQ proc pointer */
684 //cmLListDelFrm(&hqE->free, tmp);
686 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
688 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
690 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
691 /* Fix : syed minor code reorg */
693 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
695 hqE->ccchSduProc = tmpHqProc;
696 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
697 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
700 } /* rgSCHDhmGetCcchSduHqProc */
704 * @brief This function gets an available HARQ process for MSG 4.
708 * Function: rgSCHDhmGetMsg4HqProc
709 * Purpose: This function returns an available HARQ process in
710 * the DL direction. All HARQ processes are maintained
711 * in queues of free and inuse.
713 * 1. Check if the free queue is empty. If yes, return
715 * 2. If not empty, update the proc variable with the
716 * first process in the queue. Return ROK.
718 * Invoked by: scheduler
720 * @param[in] RgSchRaCb *raCb
721 * @param[in] CmLteTimingInfo timingInfo
722 * @param[out] RgDlHqProc **hqP
724 * -#ROK if successful
725 * -#RFAILED otherwise
729 S16 rgSCHDhmGetMsg4HqProc
732 CmLteTimingInfo timingInfo
735 S16 rgSCHDhmGetMsg4HqProc (raCb, timingInfo)
737 CmLteTimingInfo timingInfo;
740 RgSchDlHqProcCb *tmpHqProc;
745 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
748 /* No Harq Process available in the free queue. */
752 /* Remove the element from the free Queue and */
753 /* set the MSG 4 HARQ proc pointer */
754 //cmLListDelFrm(&hqE->free, tmp);
755 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
756 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
757 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
758 hqE->msg4Proc = tmpHqProc;
761 } /* rgSCHDhmGetMsg4HqProc */
764 * @brief This function releases a HARQ process.
768 * Function: rgSCHDhmRlsHqpTb
769 * Purpose: This function resets the TB specific fields
770 * Based on the other TBs state, this HqProcess
771 * is returned to the HqEnt.
773 * 1. Add the HARQ process to the free queue.
774 * Invoked by: scheduler and HARQ processing
776 * @param[in] RgDlHqProc *hqP
777 * @param[in] uint8_t tbIdx
778 * @param[in] Bool togNdi
783 Void rgSCHDhmRlsHqpTb
785 RgSchDlHqProcCb *hqP,
790 Void rgSCHDhmRlsHqpTb(hqP, tbIdx, togNdi)
791 RgSchDlHqProcCb *hqP;
797 uint8_t othrTbIdx = tbIdx ^ 1;
799 RgSchCmnDlHqProc *cmnHqDl;
803 RgSchDlLcCb* lcCb = NULLP;
807 /* Reset all tbInfo values */
812 if (hqP->hqE->ue != NULLP)
814 RgSchUeCb *ueCb = hqP->hqE->ue;
815 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
816 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
817 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
818 /* to get retransmission, decreasing transmission counter */
819 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
820 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
821 static uint32_t retxCnt1 = 0;
823 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
824 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
829 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
832 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
835 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
838 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
841 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
842 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
843 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
844 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
845 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
847 retxCnt1 += numDlRetx;
849 #endif /* MAC_SCH_STATS */
850 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
854 hqP->tbInfo[tbIdx].ndi ^= 1;
859 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
861 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
862 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
864 if (lcCb->lcType == CM_LTE_LCH_DTCH)
866 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
868 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
871 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
873 lcCb->qciCb->dlUeCount--;
881 hqP->tbInfo[tbIdx].tbSz = 0;
882 hqP->tbInfo[tbIdx].numLch = 0;
883 hqP->tbInfo[tbIdx].txCntr = 0;
884 /* FOR ACK NACK REP */
885 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
886 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
887 hqP->tbInfo[tbIdx].ackCount = 0;
888 /* pdcch is moved from TbCb to HqCb.
889 This pdcch will be set to NULL when
890 HqCb will be pushed to free list*/
891 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
892 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
893 hqP->tbInfo[tbIdx].nackCount = 0;
894 hqP->tbInfo[tbIdx].dtxCount = 0;
895 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
896 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
898 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
900 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
901 /* Handling msg4 hqProc */
902 if (hqE->msg4Proc == hqP)
904 hqE->msg4Proc = NULLP;
907 /* Add the proc to the free list */
908 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
909 rgSCHDhmHqPAdd2FreeLst(hqP);
913 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
914 * is dangerous and it expects ccchSduProc is the first
915 * DL allocation for a UE, and considering a scenario
916 * of multiple UEs contending and 1 UE per TTI, this
917 * assumption can be wronged, leading to inUse list
918 * corruption. Hence altering this check.
919 * A better approach would be do avoid having this
920 * special handling for ccchSduProc, streamline
921 * it with the usual approach. */
922 if (hqE->ccchSduProc == hqP)
924 hqE->ccchSduProc = NULLP;
925 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
926 * in inUse list, Hence need not to delete from inUse list*/
927 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
929 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
930 rgSCHDhmHqPDelFrmInUseLst(hqP);
934 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
938 /* Add the proc to the free list */
939 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
940 rgSCHDhmHqPAdd2FreeLst(hqP);
945 /* extra:check if other TB is also free for allocation then
946 * add it to FREE List */
947 switch(hqP->tbInfo[othrTbIdx].state)
950 /* Remove the element from the inUse Queue */
951 /* Freeing up the HARQ proc blocked for
952 * indefinite time in case of Retx */
953 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
955 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
956 rgSCHDhmHqPDelFrmInUseLst(hqP);
961 rgEmtcsetNullSubFrm(hqP);
963 /* Add the proc to the free list */
964 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
965 rgSCHDhmHqPAdd2FreeLst(hqP);
967 if (hqE->free.count > 8)
970 printf("Crashing invalid hq count after free \n");
971 printf("Crashing %d \n", *p);
976 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
979 cmnHqDl->spsAction = 0;
980 cmnHqDl->isSpsActv = FALSE;
981 cmnHqDl->isSpsSvcSchd = FALSE;
986 /* Remove the element from the inUse Queue */
987 /* Freeing up the HARQ proc blocked for
988 * indefinite time in case of Retx */
989 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
991 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
992 rgSCHDhmHqPDelFrmInUseLst(hqP);
1000 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
1003 } /* rgSCHDhmRlsHqpTb */
1006 * @brief This function releases a HARQ process.
1010 * Function: rgSCHDhmRlsHqProc
1011 * Purpose: This function returns a HARQ process to HARQ Entity
1012 * in the DL direction.
1014 * 1. Add the HARQ process to the free queue.
1015 * Invoked by: scheduler and HARQ processing
1017 * @param[in] RgDlHqProc *hqP
1022 Void rgSCHDhmRlsHqProc
1024 RgSchDlHqProcCb *hqP
1027 Void rgSCHDhmRlsHqProc(hqP)
1028 RgSchDlHqProcCb *hqP;
1033 #ifdef MAC_SCH_STATS
1034 /* THIS FUNCTION IS NOT CALLED */
1035 if (hqP->hqE->ue != NULLP)
1037 RgSchUeCb *ueCb = hqP->hqE->ue;
1038 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1039 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1040 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
1041 /* to get retransmission, decreasing transmission counter */
1042 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
1043 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1045 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
1050 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
1053 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
1056 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
1059 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
1062 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
1063 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
1064 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
1065 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
1066 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
1068 #endif /* MAC_SCH_STATS */
1070 hqP->subFrm = NULLP;
1072 rgEmtcsetNullSubFrm(hqP);
1074 rgSCHDhmHqPDelFrmInUseLst(hqP);
1075 rgSCHDhmHqPAdd2FreeLst(hqP);
1081 } /* rgSCHDhmRlsHqProc */
1085 * @brief This function gets HARQ process with the given ID.
1089 * Function: rgSCHDhmGetHqProcFrmId
1090 * Purpose: This function returns the HARQ process with the given ID.
1093 * @param[in] RgSchUeCb *ue
1094 * @param[in] uint8_t idx
1095 * @param[in] RgDlHqProc **hqP
1097 * -# ROK if successful
1098 * -# RFAILED otherwise
1102 S16 rgSCHDhmGetHqProcFrmId
1107 RgSchDlHqProcCb **hqP
1110 S16 rgSCHDhmGetHqProcFrmId(cell, ue, idx, hqP)
1114 RgSchDlHqProcCb **hqP;
1119 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1120 /* Pick the proc based on the index provided */
1121 *hqP = &(hqE->procs[idx]);
1124 } /* rgSCHDhmGetHqProcFrmId */
1127 * @brief This function gets SPS HARQ process from the given time
1131 * Function: rgSCHDhmSpsDlGetHqProc
1132 * Purpose: This function returns the SPS HARQ process for the given time
1134 * @param[in] RgSchUeCb *ue
1135 * @param[in] CmLteTimingInfo timingInfo
1136 * @return RgSchDlHqProcCb control block
1140 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc
1144 CmLteTimingInfo timingInfo
1147 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(cell, ue, timingInfo)
1150 CmLteTimingInfo timingInfo;
1155 RgSchDlHqProcCb *hqProc = NULLP;
1156 CmLList *tmp = NULLP;
1158 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1160 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1164 /* No Harq Process available in the free queue. */
1168 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1169 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1172 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1174 /* If the HARQ process is in the free list, retrieve the process */
1175 while (hqProc->procId != idx)
1177 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1182 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1187 /* No Harq Process available in the free queue. */
1191 hqProc->tbInfo[0].timingInfo = timingInfo;
1192 hqProc->tbInfo[1].timingInfo = timingInfo;
1194 /* Remove the element from the free Queue */
1195 //cmLListDelFrm(&hqE->free, tmp);
1196 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1198 /* Add the element into the inUse Queue as well */
1199 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1200 rgSCHDhmHqPAdd2InUseLst(hqProc);
1203 rgSCHLaaResetDlHqProcCb(hqProc);
1207 } /* rgSCHDhmSpsDlGetHqProc */
1208 #endif /* LTEMAC_SPS */
1211 /** * @brief Handler for handling TA.
1215 * Function : rgSCHDhmFdbkIndHndlTa
1217 * This function handles the TA state and values based on the
1218 * feedback indication received.
1220 * @param[in] RgSchDlHqProcCb *hqP
1221 * @param[in] uint8_t tbIdx
1222 * @param[in] uint8_t fdbk
1227 static Void rgSCHDhmFdbkIndHndlTa
1229 RgSchDlHqProcCb *hqP,
1232 Bool maxHqRetxReached
1235 static Void rgSCHDhmFdbkIndHndlTa(hqP, tbIdx, fdbk,maxHqRetxReached)
1236 RgSchDlHqProcCb *hqP;
1239 Bool maxHqRetxReached;
1245 ueCb = hqP->hqE->ue;
1250 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1251 hqP->tbInfo[tbIdx].taSnt = FALSE;
1252 /* To prevent duplicate inserts of ueCb into TA list */
1253 if (ueCb->taLnk.node == NULLP)
1255 ueCb->taLnk.node = (PTR)ueCb;
1256 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1261 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Trying to add CRNTI:%d into TA"
1262 "ACK List twice", ueCb->ueId);
1268 /* If Ta was sent and its the final NACK, then reset only the
1269 * taState to IDLE and not the value */
1270 /* Changed handling in case maxhqretx is reached for TA */
1271 if(TRUE == maxHqRetxReached)
1273 hqP->tbInfo[tbIdx].taSnt = FALSE;
1274 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1276 rgSCHUtlReTxTa(cell, ueCb);
1277 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
1278 "Nack Rcvd for TA. Max Tries Attempted");
1282 /* If Ta was sent and its the final NACK, then reset only the
1283 * taState to IDLE and not the value */
1284 if(TRUE == maxHqRetxReached)
1286 hqP->tbInfo[tbIdx].taSnt = FALSE;
1287 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1289 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1290 * issue for VoLTE call */
1291 rgSCHUtlDlTARpt(cell, ueCb);
1300 } /* rgSCHDhmFdbkIndHndlTa */
1302 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1303 /** * @brief Handler for scheduling TA.
1307 * Function : rgSCHDhmShcdTa
1309 * This function is called by scheduler when resource allocation
1310 * for TA transmission is done.
1312 * @param[in] RgSchUeCb *ue
1313 * @param[out] RgSchDlHqTbCb *tbInfo
1321 RgSchDlHqTbCb *tbInfo
1324 Void rgSCHDhmSchdTa(ueCb, tbInfo)
1326 RgSchDlHqTbCb *tbInfo;
1330 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1331 ueCb->dl.taCb.numRemSf = 2;
1332 tbInfo->schdTa.pres = PRSNT_NODEF;
1333 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1336 } /* rgSCHDhmSchdTa */
1339 /** * @brief Handler for fetching Harq Proc given the feeback information.
1343 * Function : rgSCHDhmHqProcByFdbkTime
1345 * This function shall fetch all the harq proc having the feedback
1346 * timing information.
1348 * @param[in] RgSchDlHqEnt *hqE
1349 * @param[in] CmLteTimingInfo timeInfo
1350 * @param[in] Bool *isMsg4
1351 * @param[out] RgSchDlHqProcCb **hqPrcs
1352 * @param[out] uint8_t *numTbs
1353 * @param[out] S8 *tbStrtIdx
1354 * @param[out] uint8_t *cntHqPrcs
1358 static S16 rgSCHDhmHqProcByFdbkTime
1361 CmLteTimingInfo timeInfo,
1363 RgSchDlHqProcCb **hqPrcs,
1370 static S16 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, isMsg4, hqPrcs,
1371 numTbs, tbStrtIdx, cntHqPrcs)
1373 CmLteTimingInfo timeInfo;
1375 RgSchDlHqProcCb **hqPrcs;
1382 RgSchDlHqTbCb *tbCb;
1383 RgSchDlHqProcCb *hqP;
1384 CmLteTimingInfo schdSfTime;
1385 RgSchTddDlAscSetIdxK ascIdx;
1396 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1399 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1400 tbStrtIdx[*cntHqPrcs] = 0;
1401 numTbs[*cntHqPrcs] = 1;
1406 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1407 noFdbks = ascIdx.numFdbkSubfrms;
1409 for(idx=0; idx<noFdbks; idx++)
1411 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1412 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1413 * serving the purpose */
1414 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1415 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1416 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1420 hqP = (RgSchDlHqProcCb*)node->node;
1423 numTbs[*cntHqPrcs] = 0;
1424 tbStrtIdx[*cntHqPrcs] = -1;
1425 for (i = 0; i < 2; i++)
1427 /* Extra:check which TB is waiting for feedback */
1428 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1430 if (tbStrtIdx[*cntHqPrcs] == -1)
1432 tbStrtIdx[*cntHqPrcs] = i;
1434 numTbs[*cntHqPrcs]++;
1437 if (numTbs[*cntHqPrcs] > 0)
1439 hqPrcs[*cntHqPrcs] = hqP;
1444 /* AN REP Hq Procs */
1445 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1448 tbCb = (RgSchDlHqTbCb *)(node->node);
1451 numTbs[*cntHqPrcs] = 0;
1452 tbStrtIdx[*cntHqPrcs] = -1;
1453 for (i = 0; i < 2; i++)
1455 /* Extra:check which TB is waiting for feedback */
1456 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1458 if (tbStrtIdx[*cntHqPrcs] == -1)
1460 tbStrtIdx[*cntHqPrcs] = i;
1462 numTbs[*cntHqPrcs]++;
1465 if (numTbs[*cntHqPrcs] == 2)
1469 if (numTbs[*cntHqPrcs] > 0)
1471 hqPrcs[*cntHqPrcs] = hqP;
1483 /** * @brief Handler for fetching Harq Proc given the timming information.
1487 * Function : rgSCHDhmHqProcByTime
1489 * This function shall fetch the harq proc using the timing information.
1491 * @param[in] RgSchDlHqEnt *hqE
1492 * @param[in] CmLteTimingInfo timeInfo
1493 * @param[in] Bool *isMsg4
1494 * @param[out] uint8_t *numTbs
1495 * @param[out] S8 *tbStrtIdx
1496 * @return RgSchDlHqProcCb*
1497 * -# RgSchDlHqProcCb*
1501 RgSchDlHqProcCb *rgSCHDhmHqProcByTime
1504 CmLteTimingInfo timeInfo,
1509 RgSchDlHqProcCb *rgSCHDhmHqProcByTime(hqE, timeInfo,
1512 CmLteTimingInfo timeInfo;
1519 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1522 return (hqE->msg4Proc);
1530 /** * @brief Handler for handling the harq transaction failure.
1534 * Function : rgSCHDhmHqTbTrnsFail
1536 * This function handled the harq TB transaction failure :
1537 * - If retries have not reached maximum, add to the reTx Q.
1538 * - else do error recovery.
1540 * @param[in] RgSchCellCb *cell
1541 * @param[in] RgSchDlHqProcCb *hqP
1542 * @param[in] uint8_t tbCnt
1543 * @param[out] Bool *isMaxRetx
1549 Void rgSCHDhmHqTbTrnsFail
1552 RgSchDlHqProcCb *hqP,
1557 Void rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, isMaxRetx)
1559 RgSchDlHqProcCb *hqP;
1569 /* Fetch the maximum number of harq transmissions */
1570 if (hqE->msg4Proc == hqP)
1573 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1575 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1576 "rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1577 hqP->hqE->raCb->tmpCrnti);
1578 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1582 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1586 maxHqTx = hqE->maxHqTx;
1589 #ifdef MAC_SCH_STATS
1590 if (hqE->ue != NULLP)
1592 RgSchUeCb *ueCb = hqE->ue;
1593 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1594 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1595 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1596 static uint32_t retxCnt = 0;
1600 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1602 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1603 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1605 #endif /* MAC_SCH_STATS */
1607 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1608 /* Reset the PDCCH reference */
1610 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1612 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1614 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1617 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1618 * for the UE. Addtion to the retransmission queue will be done on
1619 * HARQ RTT timer expiry.--*/
1620 switch(hqP->tbInfo[tbCnt ^ 1].state)
1623 /*As the first TB is ACKED we have not started HARQ RTT for the
1624 * HqP, so start it here.*/
1625 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1626 rgSCHDhmHqPDelFrmInUseLst(hqP);
1628 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1631 /* Integration fix */
1632 /* Setting cntrRetxAllocFail to MAX value here */
1633 /* Since the hqP entry is already deleted from inUse list of HqEntity
1634 setting the value here will ensure the entry is not deleted
1635 again during release harq proc */
1636 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1637 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1639 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1640 if (hqP->tbInfo[1].txCntr)
1642 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1648 /*As the first TB is NACKED we have already started HARQ RTT for the
1649 * HqP, so dont start it here, just delete from in use queue.*/
1650 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1651 rgSCHDhmHqPDelFrmInUseLst(hqP);
1654 /*As this is the first TB to be fed back and is NACKED start
1655 * the HARQ RTT here.*/
1657 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1663 /* extra:check if already removed as part of other TB processing
1664 * then donot remove from InUse Q */
1665 /* Check if other TB is not waiting for feedback.
1666 * Makinf sure hqP is present in inUse Queue until
1667 * it is fedback for all its TBs */
1668 switch(hqP->tbInfo[tbCnt ^ 1].state)
1671 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1672 if(hqE->msg4Proc != hqP)
1674 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1675 rgSCHDhmHqPDelFrmInUseLst(hqP);
1677 /* Retransmission needs to be done. Add to the scheduler Q */
1678 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1681 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1682 if(hqE->msg4Proc != hqP)
1684 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1685 rgSCHDhmHqPDelFrmInUseLst(hqP);
1689 /* Retransmission needs to be done. Add to the scheduler Q */
1691 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1699 /* Failure Notification */
1700 if (hqE->msg4Proc == hqP)
1702 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1703 rgNumMsg4FailMaxRetx++;
1705 hqE->cell->tenbStats->sch.msg4Fail ++;
1708 /* Perform RAM MSG4 done processing */
1709 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1710 "rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1711 hqP->hqE->raCb->tmpCrnti);
1712 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1716 /* Release the Harq Proc */
1717 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1723 } /* rgSCHDhmHqTbTrnsFail */
1725 uint32_t rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1726 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1729 /** * @brief Function to decode the position of HarqFb for M=1.
1733 * Function : rgSchGetHqFdbkPosForM1
1735 * @param[in] RgSchUeCb *ue,
1736 * @param[in] RgSchDlHqProcCb *hqP,
1737 * @param[in] uint8_t *isAck,
1738 * @param[in] RgTfuHqInfo *fdbk,
1739 * @param[in] uint8_t tbIdx,
1740 * @param[in] RgSchTddANInfo *anInfo;
1744 static Void rgSchGetHqFdbkPosForM1
1747 RgSchDlHqProcCb *hqP,
1751 RgSchTddANInfo *anInfo
1754 static Void rgSchGetHqFdbkPosForM1(ue,hqP,isAck,fdbk,tbIdx,anInfo)
1756 RgSchDlHqProcCb *hqP;
1760 RgSchTddANInfo *anInfo;
1765 /* handle pusch and pucch cases */
1766 /* PUSCH:: Fdbks are in the increasing order
1767 * of servCellIdx as per 36.212 section 5.2.26*/
1768 switch(ue->f1bCsAVal)
1770 case RG_SCH_A_VAL_2:
1772 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1774 *isAck = fdbk->isAck[1];/*SCell*/
1778 *isAck = fdbk->isAck[0];/*PCell*/
1782 case RG_SCH_A_VAL_3:
1784 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1786 uint8_t cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1787 hqP->hqE->cell->cellId,
1790 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1791 {/*SCell - mimo mode*/
1792 if(TRUE == fdbk->isPusch)
1794 *isAck = fdbk->isAck[tbIdx + 1];
1798 *isAck = fdbk->isAck[tbIdx];
1802 {/*SCell - siso mode*/
1803 *isAck = fdbk->isAck[2];
1807 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1808 {/*Primary Cell - mimo mode*/
1809 *isAck = fdbk->isAck[tbIdx];
1812 {/*Primary Cell - siso mode*/
1813 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1815 /* If fdbk is on PUSCH but its not an SPS occasion*/
1816 *isAck = fdbk->isAck[0];
1820 /* If fdbk is on PUCCH or its an SPS occasion*/
1821 *isAck = fdbk->isAck[2];
1827 case RG_SCH_A_VAL_4:
1829 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1831 *isAck = fdbk->isAck[tbIdx + 2];
1835 *isAck = fdbk->isAck[tbIdx];
1844 }/* End of rgSchGetHqFdbkPosForM1 */
1846 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1850 * Function : rgSchGetHqFdbkPosForM234
1852 * @param[in] RgSchUeCb *ue,
1853 * @param[in] RgSchDlHqProcCb *hqP,
1854 * @param[in] uint8_t *isAck,
1855 * @param[in] RgTfuHqInfo *fdbk,
1856 * @param[in] uint8_t tbIdx,
1857 * @param[in] RgSchTddANInfo *anInfo;
1858 * @param[in] CmLteTimingInfo timeInfo;
1862 static Void rgSchGetHqFdbkPosForM234
1865 RgSchDlHqProcCb *hqP,
1869 RgSchTddANInfo *anInfo,
1871 CmLteTimingInfo timeInfo
1874 static Void rgSchGetHqFdbkPosForM234(ue,hqP,isAck,fdbk,tbIdx,anInfo,M,timeInfo)
1876 RgSchDlHqProcCb *hqP;
1880 RgSchTddANInfo *anInfo;
1882 CmLteTimingInfo timeInfo;
1887 RgSchTddANInfo *pCellAnInfo;
1892 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1893 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1895 if(TRUE == fdbk->isPusch)
1899 if (anInfo->wUlDai == 3)
1901 incr = anInfo->wUlDai;
1907 if(1 == anInfo->ulDai)
1909 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1910 hqP->tbInfo[tbIdx].tbIdx + incr;
1914 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1919 if(1 == anInfo->ulDai)
1921 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1923 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1927 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1932 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1940 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1941 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1947 /* SPS occasion feedback in case of M > 2 will
1948 * be always present in the index 0*/
1950 if(hqP->spsN1PucchRes.pres == TRUE)
1951 {/* SPS occasion hq proc */
1955 if((NULLP != pCellAnInfo) &&
1956 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1958 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1960 {/* NO SPS occasion was present in the bundle*/
1961 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1966 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1970 *isAck = fdbk->isAck[fdbkIdx];
1972 static RgSchDlHqProcCb *temp = NULLP;
1973 if (temp != hqP->tbInfo[tbIdx].hqP)
1975 statsCnt = statsCnt % 10000;
1976 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
1977 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
1978 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot;
1979 dlHqStats[statsCnt].ack = *isAck;
1980 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
1981 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;
1983 dlHqStats[statsCnt].ulDai = incr;
1984 if(TRUE == fdbk->isPusch)
1986 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
1990 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1994 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
1995 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
1996 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
1997 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
1998 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
1999 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
2000 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
2001 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
2004 temp = hqP->tbInfo[tbIdx].hqP;
2009 }/*rgSchGetHqFdbkPosForM234*/
2013 * @brief Handler for HARQ feedback received for DL transmission.
2017 * Function : rgSCHDhmHqFdbkInd
2019 * This function shall act on the feedback received from TOM for DL
2020 * transmission. If the feedback for msg4 is final (after max transmissions
2021 * or ACK) inform RAM that Msg4 transmission is done.
2024 * @param[in] Void *cb
2025 * @param[in] uint8_t cbType
2026 * @param[in] RgSchCellCb cellCb
2027 * @param[in] CmLteTimingInfo timeInfo
2028 * @param[in] TfuHqInfo *fdbk
2029 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2030 * @param[in] RgSchErrInfo *err
2036 S16 rgSCHDhmHqFdbkInd
2040 RgSchCellCb *cellCb,
2041 CmLteTimingInfo timeInfo,
2043 RgInfRlsHqInfo *rlsHqBufs,
2047 S16 rgSCHDhmHqFdbkInd(cb, cbType, cellCb, timeInfo, fdbk, rlsHqBufs, err)
2050 RgSchCellCb *cellCb;
2051 CmLteTimingInfo timeInfo;
2053 RgInfRlsHqInfo *rlsHqBufs;
2057 RgSchCellCb *sCell = NULLP;
2059 /*ccpu00127339 - MOD - change to avoid the crash*/
2060 RgSchUeCb *ue = NULLP;
2062 Bool isMsg4 = FALSE;
2063 RgSchRaCb *raCb = NULLP;
2065 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
2066 * given feedback at a time */
2067 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
2068 uint8_t numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
2069 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
2072 RgSchTddANInfo *anInfo = NULLP;
2075 RgrTddAckNackMode ackNackMode;
2077 RgSchDlSf *nxtDlsf = NULLP;
2078 /* uint8_t rcvCnt = 0; */
2079 CmLteTimingInfo nxtfrm = {0,0};
2081 Bool maxHqRetxReached;
2083 Bool hasRelPdcch = FALSE;
2086 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2087 RgSchTddDlAscSetIdxK ascIdx;
2091 #ifdef LTEMAC_SPS_AN_MUX
2092 Bool isPusch = FALSE;
2095 /* Subframes in which transmissions are scheduled and whose feedback can come
2096 * in this subframe. Used only for Multiplexing mode */
2097 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
2098 #ifdef RGSCH_SPS_STATS
2099 RgSchCmnDlHqProc *cmnHqDl;
2103 uint8_t sCellActCePres = 0;
2105 /* LTEMAC_SPS_AN_MUX*/
2106 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
2108 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
2110 raCb = (RgSchRaCb *)(cb);
2111 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
2113 /* ccpu00139061 Fix */
2114 rnti = raCb->tmpCrnti;
2118 ue = (RgSchUeCb *)(cb);
2119 ackNackMode = ue->dl.ackNackMode;
2120 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
2122 #ifdef LTEMAC_SPS_AN_MUX
2123 isPusch = fdbk->isPusch;
2127 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
2134 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2135 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
2136 noFdbks = ascIdx.numFdbkSubfrms;
2138 #ifdef LTEMAC_SPS_AN_MUX
2139 /* Calculate the subframe time at which transmissions should have happened to
2140 * receive feedback in this subframe */
2141 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2143 for(idx=0; idx<noFdbks; idx++)
2145 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
2146 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
2147 * serving the purpose */
2148 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
2153 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
2154 tbStrtIdx, &hqCnt,hqE->cell);
2155 /* Fetch the harqProc from the inUse list */
2157 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
2161 err->errType = RGSCHERR_DHM_FDBK_IND;
2162 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2166 /* ccpu00147469 : This code is moved below as here this code always try to
2167 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
2171 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
2173 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
2179 #ifdef LTEMAC_SPS_AN_MUX
2180 /* Check if feedback came on configured UL SPS grant in Muxing mode */
2181 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
2185 /* Pick the valid feedbacks out of M feedbacks */
2186 for(idx=0; idx<noFdbks; idx++)
2188 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
2189 * and no release pdcch is sent in prevTime */
2190 /* TODO: SPS_TDD: Check this while testing */
2191 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
2192 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
2193 schdSfTime[idx])) &&
2194 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
2196 /* Discard the feedback which is corresponding to a subframe in
2197 * which no DL transmission took place */
2199 while(tmpIdx < noFdbks)
2201 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2202 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2208 } /* end of for loop */
2209 } /* end of configured UL SPS grant check */
2221 for(idx=0;idx < hqCnt; idx++)
2223 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
2227 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
2228 hqPrcs[idx]->hqE->cell->cellId,ue);
2230 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
2234 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
2236 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
2240 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
2241 "Ack Rcvd. No Ack/Nack feedback available \n"));
2246 sCell = hqPrcs[idx]->hqE->cell;
2247 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2248 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2249 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2251 /* Fix : syed MultiUe per TTI crash in TA List. */
2253 maxHqRetxReached = FALSE;
2254 /* Remove the harq process from the subframe */
2255 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2259 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2262 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2264 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2265 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2267 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2271 /* TODO: review for TM4 and CA interaction */
2272 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2274 isAck = fdbk->isAck[!tbCnt];
2278 isAck = fdbk->isAck[tbCnt];
2287 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2291 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2297 /* revanth tweakin AN PUSCH to ACK always */
2298 if (hqPrcs[idx]->isPuschFdbk)
2304 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2305 if(cellCb->ulDlCfgIdx != 5)
2307 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2308 cellCb, sf, &nxtDlsf, &nxtfrm);
2310 /* Keep a tab on how many ACKs or NACKs we have received */
2311 if (isAck == TFU_HQFDB_ACK)
2313 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2314 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2316 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2317 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2319 /* Do not update the Ul Trans Time in case of raCb */
2322 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2324 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2328 else if (isAck == TFU_HQFDB_NACK)
2330 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2331 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2333 sCell->tenbStats->sch.dlNack[tbCnt]\
2334 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2335 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2336 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2338 /* Do not update the Ul Trans Time in case of raCb */
2341 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2343 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2344 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2348 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2350 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2356 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2358 sCell->tenbStats->sch.dlDtx[tbCnt]\
2359 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2362 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2366 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2368 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2373 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2375 if(isAck == TFU_HQFDB_ACK)
2377 gSCellTb1AckCount++;
2378 gSCellTb2AckCount++;
2379 }else if(isAck == TFU_HQFDB_NACK)
2381 gSCellTb1NackCount++;
2382 gSCellTb2NackCount++;
2385 gSCellTb1DtxCount++;
2386 gSCellTb2DtxCount++;
2391 if(isAck == TFU_HQFDB_ACK)
2393 gPCellTb1AckCount++;
2394 gPCellTb2AckCount++;
2395 }else if(isAck == TFU_HQFDB_NACK)
2397 gPCellTb1NackCount++;
2398 gPCellTb2NackCount++;
2401 gPCellTb1DtxCount++;
2402 gPCellTb2DtxCount++;
2406 /* Check if this is repeating UE */
2407 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2409 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2410 /* Check if last repetition */
2411 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2413 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2414 /* Update feedback time for this hqP TB so that
2415 * next subframe its picked up */
2416 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2418 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2419 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2423 /* For a repeating UE take the decision here */
2424 /* For a repeating UE take the decision here */
2425 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2426 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2428 isAck = TFU_HQFDB_ACK;
2430 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2431 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2433 isAck = TFU_HQFDB_DTX;
2437 isAck = TFU_HQFDB_NACK;
2439 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2443 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2446 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2447 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2448 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2451 /* ACK or NACK received for SPS ACTV PDCCH
2452 * Hence consider SPS ACTVN PDCCH received successfully */
2453 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2456 if(TFU_HQFDB_ACK == isAck)
2463 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2465 /* Inform Random Access Module regarding the ack received */
2468 /*RRC Connection Setup failure issue where RRC connection
2469 * setup was not reaching UE due to message 4 HARQ failure */
2470 #ifdef XEON_SPECIFIC_CHANGES
2471 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2473 rgSCHRamMsg4Done(cellCb, raCb);
2476 else /*ccpu00114124- HARQ Release for Msg4 */
2479 /*Update feedback history for every Tx/Retx */
2480 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2482 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2483 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2485 /* Store activation CE presence as it is required later to start
2486 *activation delay timer */
2487 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2489 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2495 /* If this Msg4 DTX, there will be
2496 * no DlHqProc as it has its own HarqProc */
2499 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2500 maxHqRetxReached = hqRls;
2502 if ((isMsg4 == FALSE))
2504 /*Update feedback history for every Tx/Retx */
2505 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2508 if (isMsg4 == FALSE)
2510 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2511 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2518 /* MS_WORKAROUND: to increase Harq Fail Counter .
2519 The status field is required for tracking the number of harq faliures at MAC*/
2522 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2523 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2527 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2528 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2530 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2531 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2532 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2536 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2538 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2541 /* Handle Scell activation */
2542 if (TRUE == sCellActCePres)
2544 /* Primary Cellcb needs to be retrived
2545 * if the feedback is coming on pusch of
2546 * sec cell. THis needs to be considered
2548 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2554 hqPrcs[idx]->cwSwpEnabled = FALSE;
2556 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2558 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2559 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2560 hqPrcs[idx]->procId;
2561 rlsHqBufs->numUes++;
2564 hqPrcs[idx]->isPuschFdbk = 0;
2569 /*it is possible for some TDD configurations (like TDD cfg 5)
2570 * to have multiple feedback for 13 subframes before. It is
2571 * possible in such a case to have a release sent after data
2572 * thus running into a situation where we are receiving feedback
2573 * for both data and relese pdcch
2576 if ( (hqCnt == 0) ||
2577 (hasRelPdcch && rcvCnt > hqCnt)
2580 if (ue && hasRelPdcch)
2582 /* Bool found = FALSE; */
2584 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2594 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2595 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2597 CmLteTimingInfo txTime;
2598 uint8_t ulDlCfgIdx = 0;
2599 uint8_t maxFdbks = 0;
2602 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2604 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2608 for(itr=0; itr< maxFdbks; itr++)
2611 /* Handling the case of only SPS release pdcch
2612 * and no other scheduling in both the serving cells
2614 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2615 {/* Using the sorted K table */
2616 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2617 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2621 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2622 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2625 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2628 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2631 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2633 isAck = fdbk->isAck[0];
2636 isAck = fdbk->isAck[2];
2640 /* M > 1 same below logic apply.
2641 If SPS occasion and rel pdcch is present
2642 SPS occasion after SPS release cannot
2647 isAck = fdbk->isAck[itr];
2650 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2652 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2653 /* Remove release PDCCH from the subframe */
2654 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2655 sf->relPdcch = NULLP;
2665 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2666 /* Remove release PDCCH from the subframe */
2667 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2668 sf->relPdcch = NULLP;
2670 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2673 if ( found == FALSE )
2675 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2676 RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,"CRNTI:%d"
2677 " NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2678 ue->ueId,timeInfo.sfn, timeInfo.slot);
2679 err->errType = RGSCHERR_DHM_FDBK_IND;
2680 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2685 #endif /* LTEMAC_SPS */
2686 /* Initialise the Ack/Nack feedback */
2687 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2688 scheduling. So added a condition !isMsg4 to avoid calling the function
2689 rgSCHUtlInitUeANFdbkInfo*/
2690 if((ue) && (!anUpd) && (!isMsg4))
2693 /* TODO:: Initi the anInfo all the serving cells */
2694 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2696 if(ue->cellInfo[idx])
2698 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2699 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2700 * else don't do anything. basically continue for next serving
2704 rgSCHUtlInitUeANFdbkInfo(anInfo);
2709 rgSCHUtlInitUeANFdbkInfo(anInfo);
2715 //#endif /* LTEMAC_SPS */
2718 /** * @brief Handler for HARQ feedback received for DL transmission.
2722 * Function : rgSCHDhmPrcFdbkForTb
2724 * Process Hq Prc Fdbk for a TB
2726 * @param[in] RgSchCellCb *cell
2727 * @param[in] RgTfuHarqAckIndInfo *fdbk
2728 * @param[in] RgSchErrInfo *err
2734 S16 rgSCHDhmPrcFdbkForTb
2738 RgSchDlHqProcCb *hqP,
2743 CmLteTimingInfo timingInfo,
2745 RgInfRlsHqInfo *rlsHqBufs,
2749 S16 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt, timingInfo, isAck, rlsHqBufs, err)
2752 RgSchDlHqProcCb *hqP;
2757 CmLteTimingInfo timingInfo;
2759 RgInfRlsHqInfo *rlsHqBufs;
2764 Inst inst = cell->instIdx;
2766 #ifdef RGSCH_SPS_STATS
2767 RgSchCmnDlHqProc *cmnHqDl;
2770 RgSchRaCb *raCb = NULLP;
2772 Bool hqFreed =FALSE;
2773 Bool maxHqRetxReached = FALSE;
2774 RgSchCmnDlUe *ueDl = NULLP;
2775 RgSchCellCb *sCell = hqP->hqE->cell;
2777 RgSchEmtcDlSf *emtcSf;
2778 CmLteTimingInfo frm = timingInfo;
2783 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2786 /* Fix : syed MultiUe per TTI crash in TA List. */
2787 maxHqRetxReached = FALSE;
2789 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2790 * TODO: Need to enhance this in case of TM4 testing,
2791 * when cwSwap flag is considered. */
2793 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2794 tbCnt=%d , isAck=%d",tbCnt,isAck));
2795 if (isAck == TFU_HQFDB_ACK)
2797 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2799 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2800 /* Do not update the Ul Trans Time in case of raCb */
2803 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2805 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2811 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2812 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2817 else if (isAck == TFU_HQFDB_NACK)
2819 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2820 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2821 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2822 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2823 /* Do not update the Ul Trans Time in case of raCb */
2826 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2827 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2829 sCell->tenbStats->sch.dlNack[tbCnt]\
2830 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2837 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2839 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2840 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2843 /* Added Dl TB count for NACKED data*/
2845 if(hqP->tbInfo[tbCnt].txCntr == 1)
2847 cell->dlUlTbCnt.tbTransDlFaulty++;
2853 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2854 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2855 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2858 sCell->tenbStats->sch.dlDtx[tbCnt]\
2859 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2862 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2867 /* Added Dl TB count for DTXED data*/
2869 if(hqP->tbInfo[tbCnt].txCntr == 1)
2871 cell->dlUlTbCnt.tbTransDlFaulty++;
2876 /* Check if this is repeating UE */
2877 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2879 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2886 /* For a Normal UE take the decision here */
2887 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2889 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2892 /* Process either the ACK received or max retries have occurred */
2893 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2894 if (TFU_HQFDB_ACK == isAck)
2898 /* SR_RACH_STATS : MSG4 ACK*/
2903 raCb = rgSCHDbmGetRaCb(cell, rnti);
2905 RGSCHDBGINFO(cell->instIdx,
2906 (rgSchPBuf(cell->instIdx), "Ack Rcvd. FdbkInd for Msg4Done\n"));
2907 /* Inform Random Access Module regarding the ack received */
2910 /*RRC Connection Setup failure issue where RRC connection
2911 * setup was not reaching UE due to message 4 HARQ failure */
2912 printf("\nMSG4 Ack ,calling rgSCHRamMsg4Done\n");
2913 ret = rgSCHRamMsg4Done(cell, raCb);
2918 printf("\nraCb is NULLP\n");
2921 else /*ccpu00114124- HARQ Release for Msg4 */
2923 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2924 /* Push this harq process back to the free queue */
2925 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2927 if(hqP->tbInfo[tbCnt].txCntr == 1)
2929 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2932 RGSCH_NULL_CHECK(cell->instIdx, ue);
2933 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2934 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2943 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2944 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2946 if(hqP->tbInfo[tbCnt].txCntr == 1)
2948 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2951 RGSCH_NULL_CHECK(cell->instIdx, ue);
2952 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2956 #ifdef XEON_SPECIFIC_CHANGES
2957 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2961 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2962 maxHqRetxReached = hqRls;
2968 /* MS_WORKAROUND: to increase Harq Fail Counter .
2969 The status field is required for tracking the number of harq faliures at MAC*/
2972 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2973 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2976 else if(maxHqRetxReached)
2978 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
2979 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2980 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
2985 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2986 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2988 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2989 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2990 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2994 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
2996 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
2999 } /* rgSCHDhmPrcFdbkForTb */
3000 /** * @brief Function to decode the position of HarqFb for eachCell.
3004 * Function : rgSchGetHqFdbkPos
3006 * @param[in] RgSchCellCb *cell,
3007 * @param[in] RgSchUeCb *ue,
3008 * @param[in] RgSchDlHqProcCb *hqP,
3009 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
3010 * @param[in] Bool *isAck,
3011 * @param[in] RgTfuHqInfo *fdbk,
3015 Void rgSchGetHqFdbkPos
3019 RgSchDlHqProcCb *hqP,
3020 RgrSchFrmt1b3TypEnum uciFrmtTyp,
3025 Void rgSchGetHqFdbkPos(cell,ue,hqP,uciFrmtTyp,isAck,fdbk)
3028 RgSchDlHqProcCb *hqP;
3029 RgrSchFrmt1b3TypEnum uciFrmtTyp;
3034 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
3036 isAck[0] = fdbk->isAck[0];
3037 isAck[1] = fdbk->isAck[1];
3041 /* LAA Making all ack for LAA CELL */
3042 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
3052 /* PUSCH:: Fdbks are in the increasing order
3053 * of servCellIdx as per 36.212 section 5.2.26*/
3054 switch(ue->f1bCsAVal)
3056 case RG_SCH_A_VAL_2:
3058 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3060 isAck[0] = fdbk->isAck[1];/*SCell*/
3061 isAck[1] = fdbk->isAck[1];/*SCell*/
3065 isAck[0] = fdbk->isAck[0];/*PCell*/
3066 isAck[1] = fdbk->isAck[0];/*PCell*/
3070 case RG_SCH_A_VAL_3:
3072 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3075 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
3076 hqP->hqE->cell->cellId,
3079 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
3081 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
3083 { /* Sec cell is in mimo mode */
3084 /* use 0 and 1 for sec in case of pucch
3085 * and 1 and 2 in case of PUSCH as the primary cell is in
3086 * siso case as A =3 */
3089 isAck[0] = fdbk->isAck[0];
3090 isAck[1] = fdbk->isAck[1];
3092 {/* PUSCH as per 36.212 serction 5.2.26*/
3093 isAck[0] = fdbk->isAck[1];
3094 isAck[1] = fdbk->isAck[2];
3097 {/* sec cell is in siso */
3098 isAck[0] = fdbk->isAck[2];
3102 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3103 {/* primay cell is in mimo
3105 isAck[0] = fdbk->isAck[0];
3106 isAck[1] = fdbk->isAck[1];
3111 isAck[0] = fdbk->isAck[2];
3113 {/* PUSCH as per 36.212 serction 5.2.26*/
3114 isAck[0] = fdbk->isAck[0];
3120 case RG_SCH_A_VAL_4:
3122 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3124 isAck[0] = fdbk->isAck[2];
3125 isAck[1] = fdbk->isAck[3];
3128 if(isAck[0] == TFU_HQFDB_ACK)
3130 gSCellTb1AckCount++;
3131 }else if(isAck[0] == TFU_HQFDB_NACK)
3133 gSCellTb1NackCount++;
3136 gSCellTb1DtxCount++;
3139 if(isAck[1] == TFU_HQFDB_ACK)
3141 gSCellTb2AckCount++;
3142 }else if(isAck[1] == TFU_HQFDB_NACK)
3144 gSCellTb2NackCount++;
3147 gSCellTb2DtxCount++;
3155 isAck[0] = fdbk->isAck[0];
3156 isAck[1] = fdbk->isAck[1];
3159 if(isAck[0] == TFU_HQFDB_ACK)
3161 gPCellTb1AckCount++;
3162 }else if(isAck[0] == TFU_HQFDB_NACK)
3164 gPCellTb1NackCount++;
3167 gPCellTb1DtxCount++;
3170 if(isAck[1] == TFU_HQFDB_ACK)
3172 gPCellTb2AckCount++;
3173 }else if(isAck[1] == TFU_HQFDB_NACK)
3175 gPCellTb2NackCount++;
3178 gPCellTb2DtxCount++;
3193 }/* End of rgSchGetHqFdbkPos */
3196 Void rgSchGetHqFdbkPosFormat3
3198 RgSchDlHqProcCb *hqP,
3203 Void rgSchGetHqFdbkPosFormat3(hqP,isAck,fdbk)
3204 RgSchDlHqProcCb *hqP;
3209 uint8_t cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
3210 isAck[0] = (uint8_t)fdbk[cellIdx];
3211 isAck[1] = (uint8_t)fdbk[cellIdx + 1];
3214 /** * @brief Handler for HARQ feedback received for DL transmission.
3218 * Function : rgSCHDhm5gtfHqFdbkInd
3220 * This function shall act on the feedback received from TOM for DL
3221 * transmission. If the feedback for msg4 is final (after max transmissions
3222 * or ACK) inform RAM that Msg4 transmission is done.
3225 * @param[in] Void *cb
3226 * @param[in] uint8_t cbType
3227 * @param[in] RgSchCellCb *cell
3228 * @param[in] RgTfuHarqAckIndInfo *fdbk
3229 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3230 * @param[in] RgSchErrInfo *err
3236 S16 rgSCHDhm5gtfHqFdbkInd
3240 CmLteTimingInfo timingInfo,
3245 S16 rgSCHDhm5gtfHqFdbkInd(ue, cell, timingInfo, fdbk, err)
3248 CmLteTimingInfo timingInfo;
3253 RgSchDlHqProcCb *hqP = NULLP;
3254 CmLList *node = NULLP;
3258 Bool isMsg4 = FALSE;
3261 uint8_t hqPCount = 0;
3262 RgInfRlsHqInfo *rlsHqBufs = NULLP;
3264 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3266 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3268 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3270 hqPCount = lnk->count;
3275 hqP = (RgSchDlHqProcCb *)node->node;
3277 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3278 procId = hqP->procId;
3280 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3282 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
3284 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
3285 timingInfo, fdbk, rlsHqBufs, err);
3287 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3289 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3290 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3292 rlsHqBufs->numUes++;
3298 } /* rgSCHDhm5gtfHqFdbkInd */
3300 /** * @brief Handler for HARQ feedback received for DL transmission.
3304 * Function : rgSCHDhmHqFdbkInd
3306 * This function shall act on the feedback received from TOM for DL
3307 * transmission. If the feedback for msg4 is final (after max transmissions
3308 * or ACK) inform RAM that Msg4 transmission is done.
3311 * @param[in] Void *cb
3312 * @param[in] uint8_t cbType
3313 * @param[in] RgSchCellCb *cell
3314 * @param[in] RgTfuHarqAckIndInfo *fdbk
3315 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3316 * @param[in] RgSchErrInfo *err
3322 S16 rgSCHDhmHqFdbkInd
3327 CmLteTimingInfo timingInfo,
3329 RgInfRlsHqInfo *rlsHqBufs,
3333 S16 rgSCHDhmHqFdbkInd(cb, cbType, cell, timingInfo, fdbk, rlsHqBufs, err)
3337 CmLteTimingInfo timingInfo;
3339 RgInfRlsHqInfo *rlsHqBufs;
3343 RgSchDlHqTbCb *tbCb;
3344 RgSchDlHqEnt *hqE = NULLP;
3345 RgSchDlHqProcCb *hqP = NULLP;
3346 CmLList *node = NULLP;
3348 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3349 RgSchUeCb *ue = NULLP;
3353 Bool isMsg4 = FALSE;
3354 RgSchRaCb *raCb = NULLP;
3356 /* Added Insure Fixes Of UR.Initialized procId */
3358 /* DTX Change: Bool is converted into uint8_t*/
3359 uint8_t isAck[2]={0}; /*Changed to Array of 2*/
3361 uint8_t hqPCount = 0;
3364 CmLteTimingInfo fdbkRcptTime = timingInfo;
3365 #ifdef RGSCH_SPS_STATS
3366 RgSchCmnDlHqProc *cmnHqDl;
3370 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3372 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3374 /* Get the subframe associated with the feedback */
3375 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3376 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3377 * serving the purpose */
3378 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3380 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3381 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3383 raCb = (RgSchRaCb *)(cb);
3385 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3391 rnti = raCb->tmpCrnti;
3395 ue = (RgSchUeCb *)(cb);
3396 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3398 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3401 hqPCount = lnk->count;
3404 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3409 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3410 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3411 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3412 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3413 from get CQI from cmInfo->cqi
3414 from cmInfo get iTbs cmInfo->iTbs[0]
3415 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3416 Update stats in cellCb
3417 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3418 if (fdbk->isAck == TRUE)
3419 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3421 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3422 DL Ack/Nack statistics
3424 #ifdef MAC_SCH_STATS
3425 if (hqE->ue != NULLP)
3427 RgSchUeCb *ueCb = hqE->ue;
3428 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3429 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3430 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3431 static uint32_t retxCnt = 0;
3433 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3435 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3440 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3442 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3443 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3445 #endif /* MAC_SCH_STATS */
3447 /* Fetch the harqProc from the inUse list */
3449 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3450 /* Call Common module with the feedback information */
3451 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3453 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3455 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3458 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3459 {/* Feedback for SPS Release on PCell
3460 If Pcell is in mimo, feedback index will be 0
3462 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3464 isAck[0] = fdbk->isAck[0];
3467 isAck[0] = fdbk->isAck[2];
3470 /* Not releasing pdcch here
3471 * as it is already done at the time of
3473 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3480 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
3481 "CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3482 "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3487 isAck[0] = fdbk->isAck[0];
3488 /* Note: Since relPdcchFbkTimimg matches with the recieved
3489 * feedback, assumed that feedback is for release PDCCH */
3490 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3492 /* Remove release PDCCH from the subframe */
3493 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3494 sf->relPdcch = NULLP;
3499 #endif /* LTEMAC_SPS */
3501 /* Remove the harq process from the subframe */
3502 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3503 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3516 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3518 hqP = (RgSchDlHqProcCb *)node->node;
3520 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3522 procId = hqP->procId;
3524 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3526 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3527 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3529 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3531 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3536 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3538 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3540 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3542 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3543 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3546 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3548 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3549 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3551 rlsHqBufs->numUes++;
3556 node = sf->ackNakRepQ.first;
3559 tbCb = (RgSchDlHqTbCb *)(node->node);
3562 procId = hqP->procId;
3563 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3564 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3565 if (HQ_TB_WAITING == tbCb->state)
3567 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3568 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3569 timingInfo, isAck[0], rlsHqBufs, err);
3571 hqP->cwSwpEnabled = FALSE;
3572 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3574 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3575 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3577 rlsHqBufs->numUes++;
3584 } /* rgSCHDhmHqFdbkInd */
3585 #endif /* LTE_FDD */
3589 * @brief Handler for Harq related UE configuration.
3593 * Function : rgSCHDhmRgrUeCfg
3595 * This function shall fetch the harq related information into the
3596 * respective ueCb from the UE configuration as provided by the
3599 * @param[in] RgSchCellCb *cell
3600 * @param[in] RgSchUeCb *ueCb
3601 * @param[in] RgrUeCfg *ueCfg
3602 * @param[out] RgSchErrInfo *err
3608 Void rgSCHDhmRgrUeCfg
3616 Void rgSCHDhmRgrUeCfg(cell, ueCb, ueCfg, err)
3626 /* Initialize the TA Timer */
3627 cmInitTimers(&ueCb->taTmr, 1);
3629 /* Setting these values irrespective of taTmr value */
3630 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3631 /* Corrected default value of TA as per 36.213, 4.2.3 */
3632 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3634 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3635 ueCb->dl.taCb.outStndngTa = FALSE;
3636 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3638 /* Start TA timer only if cfgd as FINITE value */
3639 if (ueCfg->ueTaTmrCfg.pres)
3641 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3642 * TA command before the expiry of TA at UE. Also considering for
3643 * possible retx for this TA command */
3644 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3645 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3647 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3649 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3652 } /* rgSCHDhmRgrUeCfg */
3656 * @brief Handler for HARQ related UE Reconfiguration
3660 * Function : rgSCHDhmRgrCellCfg
3662 * This function shall fetch the HARQ related information into the
3663 * respective ueCb from the UE configuration as provided by the
3666 * @param[in] RgSchCellCb *cell
3667 * @param[in] RgrCellCfg *cellCfg
3668 * @param[out] RgSchErrInfo *err
3675 Void rgSCHDhmRgrCellCfg
3678 RgrCellCfg *cellCfg,
3682 Void rgSCHDhmRgrCellCfg(cell, cellCfg, err)
3684 RgrCellCfg *cellCfg;
3689 PTR pUeCb;/* previous UE Control block */
3690 PTR nUeCb;/* next UE control block */
3698 cell->dlHqCfg = cellCfg->dlHqCfg;
3701 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3709 /* Update the DL Harq related information */
3710 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3711 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3714 /* Initializing the list for ueCbs that would have ta */
3715 cmLListInit(&cell->taUeLst);
3717 cmLListInit(&cell->ccchSduUeLst);
3718 cmLListInit(&cell->contResGrdTmrLst);
3719 cmLListInit(&cell->contResTmrLst);
3721 if(cell->emtcEnable)
3723 rgSCHDhmEmtcRgrCellCfg(cell);
3728 /* Initializing the timer queue */
3729 cell->tqCp.nxtEnt = 0;
3730 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3732 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3734 cell->tq[idx].first = NULLP;
3735 cell->tq[idx].tail = NULLP;
3738 } /* rgSCHDhmRgrCellCfg */
3741 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3745 * Function : rgSCHDhmRgrCellRecfg
3747 * This function shall fetch the HARQ related information into the
3748 * respective ueCb from the UE configuration as provided by the
3751 * @param[in] RgSchCellCb *cell
3752 * @param[in] RgrCellRecfg *cellRecfg
3753 * @param[out] RgSchErrInfo *err
3760 Void rgSCHDhmRgrCellRecfg
3763 RgrCellRecfg *cellRecfg,
3767 Void rgSCHDhmRgrCellRecfg(cell, cellRecfg, err)
3769 RgrCellRecfg *cellRecfg;
3774 PTR pUeCb;/* previous UE Control block */
3775 PTR nUeCb;/* next UE control block */
3782 /* Update the cell with recieved configuration */
3783 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3785 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3789 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3797 /* Update the DL Harq related information */
3798 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3799 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3804 } /* rgSCHDhmRgrCellRecfg */
3807 * @brief Handler for freeing up the HARQ related information from ueCb
3811 * Function : rgSCHDhmFreeUe
3813 * This function shall free up the HARQ specific information from ueCb.
3815 * @param[in] RgSchUeCb *ueCb
3826 Void rgSCHDhmFreeUe(ueCb)
3831 /* If TA Timer is running. Stop it */
3832 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3834 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3837 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3838 * doesn't expire after UE is deleted */
3840 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3842 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3844 #endif /* ifdef RGR_V1*/
3847 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3849 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3852 /* This UE needs to be removed from its entry into cell's taUeLst */
3853 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3854 if(ueCb->taLnk.node)
3856 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3857 ueCb->taLnk.node = NULLP;
3860 if (ueCb->dlTaLnk.node != NULLP)
3862 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3863 * function directly from other modules. APIs should be defined and/or used
3864 * instead. Please check for other possible incorrect usage. */
3865 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3870 } /* rgSCHDhmFreeUe */
3873 * @brief Handler for updating the TA.
3877 * Function : rgSCHDhmUpdTa
3879 * This function shall update the TA received.
3881 * @param[in] RgSchCellCb *cell
3882 * @param[in] RgSchUeCb *ueCb
3883 * @param[in] uint8_t ta
3896 Void rgSCHDhmUpdTa(cell, ueCb, ta)
3903 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3905 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3906 ueCb->dl.taCb.numRemSf = 2;
3907 rgSCHUtlDlTARpt(cell, ueCb);
3908 /* If TA Timer is running. Stop it */
3909 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3911 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3914 /* SR_RACH_STATS : TA MODIFIED */
3915 if (ueCb->dl.taCb.ta != ta)
3919 ueCb->dl.taCb.ta = ta;
3923 /* [ccpu00121813]-ADD-Updating outstanding values
3924 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3925 * has been scheduled,further TA values get stored in outstndngTaval.
3926 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3927 * then schedule the outstanding TA val if present */
3928 ueCb->dl.taCb.outStndngTa = TRUE;
3929 ueCb->dl.taCb.outStndngTaval = ta;
3933 } /* rgSCHDhmUpdTa */
3935 /** @brief This function handles the TA timer expiry.
3939 * Function: This function handled the TA Expiry.
3945 * @param[in] RgSchUeCb *ueCb
3951 Void rgSCHDhmProcTAExp
3956 Void rgSCHDhmProcTAExp (ueCb)
3960 /* Ask scheduler to schedule this UE */
3961 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3962 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
3964 } /* end of rgSCHDhmProcTAExp */
3966 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
3968 * @brief Handler for Adding scheduled logical channel data information
3973 * Function : rgSCHDhmAddLcData
3975 * This function shall add the scheduled logical channel data
3976 * information to the HARQ process.
3978 * @param[in] RgSchLchAllocInfo *lchData
3979 * @param[in] RgSchDlHqTbCb *tbInfo
3985 S16 rgSCHDhmAddLcData
3988 RgSchLchAllocInfo *lchData,
3989 RgSchDlHqTbCb *tbInfo
3992 S16 rgSCHDhmAddLcData(inst, lchData, tbInfo)
3994 RgSchLchAllocInfo *lchData;
3995 RgSchDlHqTbCb *tbInfo;
3999 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
4004 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
4010 } /* rgSCHDhmAddLcData */
4014 * @brief Handler for releaseing the subframe allocation.
4018 * Function : rgSCHDhmTddRlsSubFrm
4020 * This function shall be invoked to release the DL Sf
4021 * allocations for which HARQ feedback time has expired.
4023 * @param[in] RgSchCellCb *cellCb
4024 * @param[in] CmLteTimingInfo uciTimingInfo;
4030 S16 rgSCHDhmTddRlsSubFrm
4032 RgSchCellCb *cellCb,
4033 CmLteTimingInfo uciTimingInfo
4036 S16 rgSCHDhmTddRlsSubFrm(cellCb, uciTimingInfo)
4037 RgSchCellCb *cellCb;
4038 CmLteTimingInfo uciTimingInfo;
4041 CmLteTimingInfo dlSfTime;
4042 RgSchTddDlAscSetIdxK ascIdx;
4047 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4048 noFdbks = ascIdx.numFdbkSubfrms;
4049 for(i=0; i < noFdbks; i++)
4051 /* Get the subframe and sfn for which HARQ Ack/Nack
4053 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4054 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4055 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4056 * as it is serving the purpose */
4057 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4058 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
4061 }/* rgSCHDhmTddRlsSubFrm */
4064 uint32_t macDtx = 0;
4067 * @brief Handler for Removing the HARQ process from a dlsf.
4071 * Function : rgSCHDhmRlsDlsfHqProc
4073 * This function shall be invoked for every tti. It goes back to
4074 * to the sixth last subframe to check whether it still exists. If
4075 * that exists this function traverses through the entire harq
4076 * proc list associated and frees up all of them.
4078 * @param[in] RgSchCellCb *cellCb
4079 * @param[in] CmLteTimingInfo timingInfo
4085 S16 rgSCHDhmRlsDlsfHqProc
4087 RgSchCellCb *cellCb,
4088 CmLteTimingInfo uciTimingInfo
4091 S16 rgSCHDhmRlsDlsfHqProc(cellCb, uciTimingInfo)
4092 RgSchCellCb *cellCb;
4093 CmLteTimingInfo uciTimingInfo;
4097 CmLteTimingInfo dlSfTime;
4098 CmLteTimingInfo nxtfrm = {0,0};
4099 RgSchDlHqProcCb *tmpHqProc;
4100 RgSchTddDlAscSetIdxK ascIdx;
4103 RgSchDlSf *nxtDlsf = NULLP;
4107 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
4108 uint8_t maxRetx=FALSE;
4109 RgSchTddANInfo *anInfo = NULLP;
4110 RgSchDlHqTbCb *tbCb;
4111 RgSchUeCb *ue = NULLP;
4114 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4115 noFdbks = ascIdx.numFdbkSubfrms;
4116 for(i=0; i < noFdbks; i++)
4118 /* Get the subframe and sfn for which HARQ Ack/Nack
4120 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4121 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4122 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4123 * as it is serving the purpose */
4124 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4126 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
4127 if(cellCb->ulDlCfgIdx != 5)
4129 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
4131 /* Subframe is present. Delete all the harq associations from
4135 /*Handling for Msg4*/
4136 node = dlSf->msg4HqPLst.first;
4139 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4141 tmpHqProc->cwSwpEnabled = FALSE;
4142 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4144 tbCb = &tmpHqProc->tbInfo[0];
4146 /* Fix : syed MultiUe per TTI crash in TA List. */
4150 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4153 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4155 /* Delete the Harq Association. Release the Harq Process */
4156 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4158 if (tbCb->taSnt == TRUE)
4160 /* [ccpu00127148] Correcting the check */
4161 if (TRUE == maxRetx)
4163 tbCb->taSnt = FALSE;
4164 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4165 ue->dl.taCb.state = RGSCH_TA_IDLE;
4167 rgSCHUtlReTxTa(cellCb, ue);
4173 node = dlSf->ueLst.first;
4179 ue = (RgSchUeCb *)(node->node);
4183 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
4186 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4187 hqPNode = hqPNode->next;
4188 for (idx = 0 ;idx < 2; idx++)
4190 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4192 tbCb = &tmpHqProc->tbInfo[idx];
4194 /* Fix : syed MultiUe per TTI crash in TA List. */
4198 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4201 /* Update feedback time for this process so that
4202 * next subframe its picked up */
4204 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
4205 tmpHqProc->hqE->cell->instIdx,
4206 tmpHqProc->hqE->cell->cellId,
4208 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4210 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
4214 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
4215 "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX"
4216 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
4217 uciTimingInfo.slot));
4219 else if (tbCb->fbkRepCntr == 0)
4221 /* Initialise the Ack/Nack feedback */
4223 if(!(anInfo->dlDai))
4225 rgSCHUtlInitUeANFdbkInfo(anInfo);
4230 /* Update feedback time for this process so that
4231 * * next subframe its picked up */
4232 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4233 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4234 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4235 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
4240 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4241 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
4244 /* Delete the Harq Association. Release the Harq Process */
4245 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4247 if (tbCb->taSnt == TRUE)
4249 /* [ccpu00127148] Correcting the check */
4250 if (TRUE == maxRetx)
4252 tbCb->taSnt = FALSE;
4253 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4254 ue->dl.taCb.state = RGSCH_TA_IDLE;
4256 rgSCHUtlReTxTa(cellCb, ue);
4258 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4259 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4268 node = dlSf->ackNakRepQ.first;
4271 tbCb = (RgSchDlHqTbCb *)(node->node);
4272 tmpHqProc = tbCb->hqP;
4273 /* [ccpu00121813]-ADD-Fetch ueCb */
4274 ue = tmpHqProc->hqE->ue;
4275 /* Fix : syed MultiUe per TTI crash in TA List. */
4280 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
4281 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
4285 /* If This is not the last repetition */
4286 if (tbCb->fbkRepCntr > 1)
4288 /* Update feedback time for this process so that
4289 * next subframe its picked up */
4291 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
4292 tmpHqProc->hqE->cell->instIdx,
4293 tmpHqProc->hqE->cell->cellId,
4295 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4297 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
4303 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4304 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4305 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4306 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4312 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4314 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
4316 /*even if one NACK, we consider the feedback
4317 * on a whole as NACk */
4318 if ( tbCb->nackCount != 0 )
4320 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4324 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4328 /* Delete the Harq Association. Release the Harq Process */
4329 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4331 }/*if(((tbCb->nackCount+....*/
4334 if (tbCb->taSnt == TRUE)
4336 /* [ccpu00127148] Correcting the check */
4337 if (TRUE == maxRetx)
4339 tbCb->taSnt = FALSE;
4340 ue->dl.taCb.state = RGSCH_TA_IDLE;
4342 rgSCHUtlReTxTa(cellCb, ue);
4343 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4344 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4351 }/* rgSCHDhmRlsDlsfHqProc */
4352 #else /* ifdef LTE_TDD */
4354 * @brief Handler for Removing the HARQ process from a dlsf.
4358 * Function : rgSCHDhmRlsDlsfHqProc
4360 * This function shall be invoked for every tti. It goes back to
4361 * to the sixth last subframe to check whether it still exists. If
4362 * that exists this function traverses through the entire harq
4363 * proc list associated and frees up all of them.
4365 * @param[in] RgSchCellCb *cell
4371 S16 rgSCHDhmRlsDlsfHqProc
4374 CmLteTimingInfo timingInfo
4377 S16 rgSCHDhmRlsDlsfHqProc(cell, timingInfo)
4379 CmLteTimingInfo timingInfo;
4383 CmLteTimingInfo frm;
4384 RgSchDlHqProcCb *tmpHqProc;
4389 RgSchDlHqTbCb *tbCb;
4392 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
4393 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4394 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4395 * as it is serving the purpose */
4396 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
4399 /* Get the required Last subframe */
4400 sf = rgSCHUtlSubFrmGet(cell, frm);
4403 /*Handling for Msg4*/
4404 node = sf->msg4HqPLst.first;
4407 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4408 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4410 tbCb = &tmpHqProc->tbInfo[0];
4411 /* Fix : syed MultiUe per TTI crash in TA List. */
4414 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4415 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4418 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4419 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4421 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4426 if (tbCb->fbkRepCntr != 0)
4428 /* Update timingInfo for this hqP so that next subframe its picked up */
4429 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4430 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4434 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4436 /* Delete the Harq Association. Release the Harq Process */
4437 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4441 /* Subframe is present. Delete all the harq associations from
4444 node = sf->ueLst.first;
4447 ue = (RgSchUeCb *)(node->node);
4451 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4455 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4456 tmpHqProc->cwSwpEnabled = FALSE;
4457 hqPNode = hqPNode->next;
4458 for (idx = 0 ;idx < 2; idx++)
4460 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4462 tbCb = &tmpHqProc->tbInfo[idx];
4463 /* Fix : syed MultiUe per TTI crash in TA List. */
4466 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4467 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4470 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4471 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4473 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4478 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4481 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4484 /* Delete the Harq Association. Release the Harq Process */
4485 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4487 if (tbCb->taSnt == TRUE)
4489 /* [ccpu00127148] Correcting the check */
4490 if (TRUE == maxRetx)
4492 tbCb->taSnt = FALSE;
4493 ue->dl.taCb.state = RGSCH_TA_IDLE;
4495 rgSCHUtlReTxTa(cell, ue);
4496 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4497 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4500 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4501 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4510 } /* rgSCHDhmRlsDlsfHqProc */
4515 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4520 * Function: rgSCHDhmMarkSpsHqProc
4521 * Purpose: This function returns the HARQ process with the given ID.
4522 * Invoked by: SPS Module
4524 * - Get the HARQ process by index from the UE
4525 * - Set isSpsHqProc = TRUE
4527 * @param[in] RgSchUeCb *ue
4528 * @param[in] uint8_t idx
4530 * -# ROK if successful
4531 * -# RFAILED otherwise
4535 S16 rgSCHDhmMarkSpsHqProc
4541 S16 rgSCHDhmMarkSpsHqProc(ue, idx)
4546 RgSchDlHqProcCb *hqP;
4548 /* Pick the proc based on the index provided */
4549 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4552 } /* rgSCHDhmMarkSpsHqProc */
4553 #endif /* RG_UNUSED */
4554 #endif /* LTEMAC_SPS */
4557 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4561 * Function : rgSCHDhmProcHqFdbkAckNackRep
4563 * This function shall act on the feedback received from TOM for DL
4567 * @param[in] RgSchDlHqProcCb *hqP
4568 * @param[in] RgSchDlSf *sf
4569 * @param[in] uint8_t tbCnt
4570 * @param[in] uint8_t *isAck
4576 static S16 rgSCHDhmProcHqFdbkAckNackRep
4578 RgSchDlHqProcCb *hqP,
4584 static S16 rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,isAck)
4585 RgSchDlHqProcCb *hqP;
4591 /* Check if this is repeating UE */
4592 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4593 /* Check if last repetition */
4594 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4596 /* Update timingInfo for this hqP so that next subframe its picked up */
4597 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4598 hqP->tbInfo[tbCnt].timingInfo, 1);
4602 /* Take decision here based on the number
4603 * of DTX's,NACK's and ACK's received
4605 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4606 (hqP->tbInfo[tbCnt].dtxCount)))
4608 *isAck = TFU_HQFDB_ACK;
4610 /*even a single NACK indicates that UE received
4613 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4615 *isAck = TFU_HQFDB_NACK;
4619 *isAck = TFU_HQFDB_DTX;
4623 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4626 #endif /* ifndef LTE_TDD */
4629 /* Freeing up the HARQ proc blocked for
4630 * indefinite time in case of Retx */
4632 * @brief This function handles the scenario in case Retx allocation is failed.
4636 * Function: rgSCHDhmDlRetxAllocFail
4639 * @param[in] RgSchUeCb *ue
4640 * @param[in] RgSchDlHqProcCb *hqP
4645 S16 rgSCHDhmDlRetxAllocFail
4648 RgSchDlHqProcCb *hqP
4651 S16 rgSCHDhmDlRetxAllocFail(ue, hqP)
4653 RgSchDlHqProcCb *hqP;
4657 RgInfRlsHqInfo *rlsHqInfo;
4659 Bool maxRetx = FALSE;
4660 RgSchCmnCell *cellSch;
4662 cell = hqP->hqE->cell;
4663 cellSch = RG_SCH_CMN_GET_CELL(cell);
4664 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4666 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4667 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4669 hqP->tbInfo[0].cntrRetxAllocFail++;
4672 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4673 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4675 hqP->tbInfo[1].cntrRetxAllocFail++;
4678 /* initialize MAC-SCH interface HARQ release info */
4679 rlsHqInfo->numUes = 0;
4680 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4682 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4683 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4685 if (hqP->hqE->msg4Proc == hqP)
4687 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4691 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4694 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4699 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4700 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4704 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4705 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4708 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4709 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4712 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4713 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4714 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4717 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4718 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4720 if (hqP->hqE->msg4Proc == hqP)
4722 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4726 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4729 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4731 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4732 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4733 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4734 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4735 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4738 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4740 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4741 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4743 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4746 /* send HARQ release to MAC */
4747 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4749 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4750 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4751 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4752 rlsHqInfo->numUes = 1;
4754 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4755 RgSchMacRlsHq(&pst, rlsHqInfo);
4763 static S16 rgSCHDhmUpdateAckNackHistory
4771 static S16 rgSCHDhmUpdateAckNackHistory(cell, ueCb, hqfdbk, tbCnt)
4782 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4785 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4788 if (hqfdbk == TFU_HQFDB_ACK)
4790 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4794 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4797 printf("deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4798 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4799 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4802 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4808 S16 rgSCHDhmUpdBlerBasediTbsEff
4815 S16 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt)
4825 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4826 uint8_t cfi = cellSch->dl.currCfi;
4827 uint8_t maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4828 maxiTbs = RG_SCH_DL_MAX_ITBS;
4830 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4831 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4835 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4836 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4840 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4841 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4845 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4846 ueDl->laCb[tbCnt].deltaiTbs)/100),
4847 ueCb->cell->thresholds.maxDlItbs);
4850 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4852 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4854 /* Eff for CW for 1 Layer Tx */
4855 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4856 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4857 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4859 /* Eff for CW for 2 Layer Tx */
4860 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4861 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4862 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4870 * @brief This function Processes the Hq Fdbk in case of
4871 * special Bundling in TDD (FAPIv1.1: Table 79)
4875 * Function: rgSCHDhmPrcSplBundlFdbk
4876 * Purpose: To Interpret the Harq Feedback according to
4877 * table 7.3-1: 36.213
4879 * 0 = 0 or None (UE detect at least one DL is missed)
4880 * 1 = 1 or 4 or 7 ACKs reported
4881 * 2 = 2 or 5 or 8 ACKs reported
4882 * 3 = 3 or 6 or 9 ACKs reported
4883 * 4 = DTX (UE did not transmit anything)
4885 * @param[in] TfuHqInfo *fdbk
4886 * @param[in] uint8_t hqCnt
4891 static Void rgSCHDhmPrcSplBundlFdbk
4898 static Void rgSCHDhmPrcSplBundlFdbk(cell, fdbk, hqCnt)
4908 /* Num of ACKs reported by UE */
4909 numOfAcks = fdbk->isAck[0];
4911 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4912 fdbk->isAck[0] == TFU_HQFDB_DTX)
4918 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4919 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4921 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4924 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4925 the PDSCH trasnmission (spatial bundling). So we have
4926 to assume same feedback for both codewords */
4928 for(uint8_t idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4930 fdbk->isAck[idx] = fdbk->isAck[0];
4933 fdbk->isAck[1] = fdbk->isAck[0];
4941 * @brief This function adds HARQ process to FREE list
4945 * Function: rgSCHDhmHqPAdd2FreeLst
4948 * Invoked by: scheduler
4950 * @param[out] RgDlHqProc *hqP
4955 Void rgSCHDhmHqPAdd2FreeLst
4957 RgSchDlHqProcCb *hqP
4960 Void rgSCHDhmHqPAdd2FreeLst(hqP)
4961 RgSchDlHqProcCb *hqP;
4969 printf("Crashing already part of free lst\n");
4970 printf("Crashing %d \n", *p);
4974 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
4975 hqP->hqPLst = &hqP->hqE->free;
4979 if (hqP->hqE->free.count > 8)
4982 printf("Crashing invalid hq count\n");
4983 printf("Crashing %d \n", *p);
4989 rgSCHLaaHndlHqProcFree(hqP);
4993 } /* rgSCHDhmHqPAdd2FreeLst */
4997 * @brief This function adds HARQ process to inUse list
5001 * Function: rgSCHDhmHqPAdd2InUseLst
5004 * Invoked by: scheduler
5006 * @param[out] RgDlHqProc *hqP
5011 Void rgSCHDhmHqPAdd2InUseLst
5013 RgSchDlHqProcCb *hqP
5016 Void rgSCHDhmHqPAdd2InUseLst(hqP)
5017 RgSchDlHqProcCb *hqP;
5025 printf("Crashing already part of inuse lst\n");
5026 printf("Crashing %d \n", *p);
5030 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
5031 hqP->hqPLst = &hqP->hqE->inUse;
5035 if (hqP->hqE->inUse.count > 8)
5038 printf("Crashing invalid hq count \n");
5039 printf("Crashing %d \n", *p);
5045 } /* rgSCHDhmHqPAdd2InUseLst */
5048 * @brief This function adds HARQ process to FREE list
5052 * Function: rgSCHDhmHqPDelFrmFreeLst
5055 * Invoked by: scheduler
5057 * @param[out] RgDlHqProc *hqP
5062 Void rgSCHDhmHqPDelFrmFreeLst
5064 RgSchDlHqProcCb *hqP
5067 Void rgSCHDhmHqPDelFrmFreeLst(hqP)
5068 RgSchDlHqProcCb *hqP;
5076 printf("Crashing not part of any lst\n");
5077 printf("Crashing %d \n", *p);
5082 if (hqP->hqPLst != &hqP->hqE->free)
5085 printf("Crashing del from wrong lst\n");
5086 printf("Crashing %d \n", *p);
5091 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
5092 hqP->hqPLst = NULLP;
5095 if (hqP->hqE->free.count > 8)
5098 printf("Crashing invalid hq count\n");
5099 printf("Crashing %d \n", *p);
5105 } /* rgSCHDhmHqPDelFrmFreeLst */
5110 * @brief This function adds HARQ process to FREE list
5114 * Function: rgSCHDhmHqPDelFrmInUseLst
5117 * Invoked by: scheduler
5119 * @param[out] RgDlHqProc *hqP
5124 Void rgSCHDhmHqPDelFrmInUseLst
5126 RgSchDlHqProcCb *hqP
5129 Void rgSCHDhmHqPDelFrmInUseLst(hqP)
5130 RgSchDlHqProcCb *hqP;
5138 printf("Crashing not part of any lst\n");
5139 printf("Crashing %d \n", *p);
5145 if (hqP->hqPLst != &hqP->hqE->inUse)
5148 printf("Crashing del from wrong lst\n");
5149 printf("Crashing %d \n", *p);
5154 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
5155 hqP->hqPLst = NULLP;
5158 if (hqP->hqE->inUse.count > 8)
5161 printf("Crashing invalid hq count\n");
5162 printf("Crashing %d \n", *p);
5168 } /* rgSCHDhmHqPDelFrmInUseLst */
5171 /**********************************************************************
5174 **********************************************************************/