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 extern U32 rgNumSPSSchedDropMaxRetx;
64 extern U32 rgNumActDtx;
66 PUBLIC U32 nackSf[10];
71 PUBLIC RgSchNackAckStats hqFailStats;
72 PUBLIC 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 U8 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 PRIVATE Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, U8 tbIdx, U8 fdbk,
105 Bool maxHqRetxReached));
106 PUBLIC void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
108 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
109 RgSchDlHqProcCb *hqP,
116 PRIVATE S16 rgSCHDhmUpdateAckNackHistory ARGS((
124 PRIVATE Void rgSCHDhmPrcSplBundlFdbk ARGS((
130 PRIVATE Void rgSchGetHqFdbkPosForM1 ARGS((
132 RgSchDlHqProcCb *hqP,
136 RgSchTddANInfo *anInfo
138 PRIVATE 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 PUBLIC S16 rgSCHDhmDlRetxAllocFail ARGS((
155 RgSchDlHqProcCb *proc
159 EXTERN S16 rgSCHDhmEmtcRgrCellCfg ARGS((
165 extern U32 gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
166 extern U32 gSCellSchedCount,gPrimarySchedCount;
167 extern U32 gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
168 extern U32 gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
169 extern U32 gHqFdbkCount;
173 EXTERN Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
175 RgSchEmtcDlSf *subFrm,
176 RgSchDlHqProcCb *hqP,
180 EXTERN RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
185 EXTERN 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 PUBLIC Void rgSCHDhmHqEntReset
212 PUBLIC Void rgSCHDhmHqEntReset(hqE)
216 RgSchDlHqProcCb *hqP;
218 TRC2(rgSCHDhmHqEntReset)
219 cmLListInit(&hqE->inUse);
220 cmLListInit(&hqE->free);
221 for (i=0; i < hqE->numHqPrcs; i++)
223 hqP = &hqE->procs[i];
226 /* Fix - reset numLch */
227 hqP->tbInfo[0].numLch = 0;
228 hqP->tbInfo[1].numLch = 0;
229 hqP->tbInfo[0].txCntr = 0;
230 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
231 hqP->tbInfo[1].txCntr = 0;
232 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
233 hqP->tbInfo[0].tbIdx = 0;
234 hqP->tbInfo[1].tbIdx = 1;
235 hqP->tbInfo[0].hqP = hqP;
236 hqP->tbInfo[1].hqP = hqP;
237 hqP->tbInfo[0].state = HQ_TB_ACKED;
238 hqP->tbInfo[1].state = HQ_TB_ACKED;
239 hqP->tbInfo[0].contResCe = NOTPRSNT;
240 hqP->tbInfo[1].contResCe = NOTPRSNT;
241 hqP->lnk.node = (PTR)hqP;
242 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
244 rgSCHDhmHqPAdd2FreeLst(hqP);
245 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
246 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
247 hqP->drxCb.rttIndx = DRX_INVALID;
248 hqP->drxCb.reTxIndx = DRX_INVALID;
249 hqP->tbInfo[0].cntrRetxAllocFail = 0;
250 hqP->tbInfo[1].cntrRetxAllocFail = 0;
251 hqP->hasDcch = FALSE;
252 hqP->cwSwpEnabled = FALSE;
257 rgSCHLaaResetDlHqProcCb(hqP);
261 } /* rgSCHDhmHqEntReset */
264 * @brief This function assigns dlHqEnt of raCb to ueCb.
268 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
269 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
271 * Invoked by: configuration module
273 * @param[in] RgSchUeCb *ue
274 * @param[in] RgSchRaCb *raCb
279 PUBLIC Void rgSCHDhmAssgnUeHqEntFrmRaCb
285 PUBLIC Void rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb)
290 TRC2(rgSCHDhmAssgnUeHqEntFrmRaCb)
292 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
293 ue->cellInfo[0]->hqEnt->ue = ue;
294 /* Update the DL Harq related information */
295 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
297 /* Fix : set UE active in DL as UE initialization completed */
298 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
299 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
300 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
306 * @brief This function deletes the dlHqEnt.
310 * Function: rgSCHDhmDelHqEnt
311 * Purpose: This function deletes the dlHqEnt.
313 * Invoked by: configuration module
315 * @param[in] RgSchCellCb *cell
316 * @param[in] RgSchDlHqEnt **hqE
321 PUBLIC Void rgSCHDhmDelHqEnt
327 PUBLIC Void rgSCHDhmDelHqEnt(cell, hqE)
332 TRC2(rgSCHDhmDelHqEnt)
339 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
341 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
342 sizeof(RgSchDlHqEnt));
348 PUBLIC RgSchDlHqEnt *rgSCHDhmHqEntInit
353 PUBLIC RgSchDlHqEnt *rgSCHDhmHqEntInit(cell)
358 Inst inst = cell->instIdx;
360 TRC2(rgSCHDhmHqEntInit)
362 /* Init the HARQ data structure */
363 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
365 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
366 "rgSCHDhmHqEntInit hqE alloc fail");
370 /* Init the HARQ processes */
371 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
372 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
373 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
375 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
376 "rgSCHDhmHqEntInit hqP alloc fail in hqE");
380 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
384 rgSCHLaaInitDlHqProcCb (cell, hqE);
387 /* Initialize maximum tranmission counter */
388 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
391 /* MW_WORKAROUND for ccpu00122893 */
392 rgSCHDhmHqEntReset(hqE);
398 } /* rgSCHDhmHqEntInit */
401 * @brief This function gets an available HARQ process.
405 * Function: rgSCHDhmGetAvlHqProc
406 * Purpose: This function returns an available HARQ process in
407 * the DL direction. All HARQ processes are maintained
408 * in queues of free and inuse.
410 * 1. Check if the free queue is empty. If yes, return
412 * 2. If not empty, update the proc variable with the
413 * first process in the queue. Return ROK.
415 * Invoked by: scheduler
417 * @param[in] RgSchUeCb *ue
418 * @param[in] CmLteTimingInfo timingInfo
419 * @param[out] RgSchDlHqProc **hqP
421 * -#ROK if successful
422 * -#RFAILED otherwise
426 PUBLIC S16 rgSCHDhmGetAvlHqProc
430 CmLteTimingInfo timingInfo,
431 RgSchDlHqProcCb **hqP
434 PUBLIC S16 rgSCHDhmGetAvlHqProc (cell, ue, timingInfo, hqP)
437 CmLteTimingInfo timingInfo;
438 RgSchDlHqProcCb **hqP;
441 RgSchDlHqEnt *hqE = NULLP;
442 RgSchDlHqProcCb *tmpHqProc;
444 TRC2(rgSCHDhmGetAvlHqProc);
446 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
450 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDhmGetAvlHqProc hqE NULL ue %d"
456 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
460 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
461 "rgSCHDhmGetAvlHqProc free %ld inUse %ld ue %d"
462 , hqE->free.count, hqE->inUse.count, ue->ueId);
463 /* No Harq Process available in the free queue. */
467 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
470 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
472 if (ue->dl.isSpsHqPInUse)
474 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
476 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
481 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
485 /* No Harq Process available in the free queue. */
492 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
493 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
494 tmpHqProc->hasDcch = FALSE;
495 tmpHqProc->cwSwpEnabled = FALSE;
497 /* Remove the element from the free Queue */
498 //cmLListDelFrm(&hqE->free, tmp);
499 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
501 /* Add the element into the inUse Queue as well */
502 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
503 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
508 rgSCHLaaResetDlHqProcCb(tmpHqProc);
512 tmpHqProc->tbSizeAtEstimate[0] = 0;
513 tmpHqProc->tbSizeAtEstimate[1] = 0;
514 tmpHqProc->tbSizeAtFnlz[0] = 0;
515 tmpHqProc->tbSizeAtFnlz[1] = 0;
516 tmpHqProc->tbSizeOfMvdTb[0] = 0;
517 tmpHqProc->tbSizeOfMvdTb[1] = 0;
518 tmpHqProc->itbsAtEstimate[0] = 0;
519 tmpHqProc->itbsAtEstimate[1] = 0;
520 tmpHqProc->prbAtEstimate = 0;
523 } /* rgSCHDhmGetAvlHqProc */
527 * @brief This function adds HARQ process for a given TB in to
528 * the inuse queue upon retx.
532 * Function: rgSCHDhmHqTbRetx
533 * Purpose: This function handles when a HARQ process is scheduled
534 * for retransmission. It adds the HARQ procss to inuse
536 * 1. Check if this HqP is already added to the inUse
537 * queue as part of this function call for other
538 * TB's retransmission.
539 * 2. If already present in inUse Q then do not add.
541 * Invoked by: scheduler
543 * @param[in] RgSchDlHqEnt *hqE
544 * @param[in] CmLteTimingInfo timingInfo
545 * @param[out] RgDlHqProc *hqP
546 * @param[in] U8 tbIdx
551 PUBLIC Void rgSCHDhmHqTbRetx
554 CmLteTimingInfo timingInfo,
555 RgSchDlHqProcCb *hqP,
559 PUBLIC Void rgSCHDhmHqTbRetx(hqE, timingInfo, hqP, tbIdx)
561 CmLteTimingInfo timingInfo;
562 RgSchDlHqProcCb *hqP;
566 U8 othrTbIdx = tbIdx ^ 1;
567 TRC2(rgSCHDhmHqTbRetx)
569 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
571 if (hqE->msg4Proc == hqP)
575 /* fix for ccpu00118633 No Hq proc Avl end*/
577 /* Extra:check if Harq process is already linked to in-use
578 Queue by means of other TB handling. */
579 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
582 if (hqE->msg4Proc != hqP)
584 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
585 rgSCHDhmHqPAdd2InUseLst(hqP);
589 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
592 } /* rgSCHDhmHqTbRetx */
595 * @brief This function returns last scheduled HARQ process for
596 * a UE's HARQ entity.
600 * Function: rgSCHDhmLastSchedHqProc
601 * Purpose: This function returns the last (most recent)
602 * process in the inUse list, which corresponds
603 * to the last scheduled process. Returns NULLP
605 * The reason for introducing this is to have
606 * an ability to check if UE was scheduled
607 * in the current subframe (scheduling would
608 * have caused a proc to be added to the end
609 * of the list, and checking time (only subframe
610 * number probably works) would confirm this.
612 * Invoked by: scheduler
614 * @param[in] RgSchDlHqEnt *hqE
615 * @return RgSchDlHqProcCb *
619 PUBLIC RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc
624 PUBLIC RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(hqE)
628 TRC2(rgSCHDhmLastSchedHqProc);
629 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
630 * until RACH procedure is completed */
631 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
635 return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
636 } /* rgSCHDhmLastSchedHqProc */
640 * @brief This function gets an available HARQ process for MSG 4.
644 * Function: rgSCHDhmGetCcchSduHqProc
645 * Purpose: This function returns an available HARQ process in
646 * the DL direction. All HARQ processes are maintained
647 * in queues of free and inuse.
649 * 1. Check if the free queue is empty. If yes, return
651 * 2. If not empty, update the proc variable with the
652 * first process in the queue. Return ROK.
654 * Invoked by: scheduler
656 * @param[in] RgSchRaCb *raCb
657 * @param[in] CmLteTimingInfo timingInfo
658 * @param[out] RgSchDlHqProcCb **hqP
660 * -#ROK if successful
661 * -#RFAILED otherwise
665 PUBLIC S16 rgSCHDhmGetCcchSduHqProc
668 CmLteTimingInfo timingInfo,
669 RgSchDlHqProcCb **hqP
672 PUBLIC S16 rgSCHDhmGetCcchSduHqProc (ueCb, timingInfo, hqP)
674 CmLteTimingInfo timingInfo;
675 RgSchDlHqProcCb **hqP;
678 RgSchDlHqProcCb *tmpHqProc;
682 TRC2(rgSCHDhmGetCcchSduHqProc)
684 hqE = ueCb->cellInfo[0]->hqEnt;
685 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
688 /* No Harq Process available in the free queue. */
692 /* Remove the element from the free Queue and */
693 /* set the MSG 4 HARQ proc pointer */
694 //cmLListDelFrm(&hqE->free, tmp);
696 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
698 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
700 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
701 /* Fix : syed minor code reorg */
703 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
705 hqE->ccchSduProc = tmpHqProc;
706 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
707 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
710 } /* rgSCHDhmGetCcchSduHqProc */
714 * @brief This function gets an available HARQ process for MSG 4.
718 * Function: rgSCHDhmGetMsg4HqProc
719 * Purpose: This function returns an available HARQ process in
720 * the DL direction. All HARQ processes are maintained
721 * in queues of free and inuse.
723 * 1. Check if the free queue is empty. If yes, return
725 * 2. If not empty, update the proc variable with the
726 * first process in the queue. Return ROK.
728 * Invoked by: scheduler
730 * @param[in] RgSchRaCb *raCb
731 * @param[in] CmLteTimingInfo timingInfo
732 * @param[out] RgDlHqProc **hqP
734 * -#ROK if successful
735 * -#RFAILED otherwise
739 PUBLIC S16 rgSCHDhmGetMsg4HqProc
742 CmLteTimingInfo timingInfo
745 PUBLIC S16 rgSCHDhmGetMsg4HqProc (raCb, timingInfo)
747 CmLteTimingInfo timingInfo;
750 RgSchDlHqProcCb *tmpHqProc;
754 TRC2(rgSCHDhmGetMsg4HqProc)
757 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
760 /* No Harq Process available in the free queue. */
764 /* Remove the element from the free Queue and */
765 /* set the MSG 4 HARQ proc pointer */
766 //cmLListDelFrm(&hqE->free, tmp);
767 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
768 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
769 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
770 hqE->msg4Proc = tmpHqProc;
773 } /* rgSCHDhmGetMsg4HqProc */
776 * @brief This function releases a HARQ process.
780 * Function: rgSCHDhmRlsHqpTb
781 * Purpose: This function resets the TB specific fields
782 * Based on the other TBs state, this HqProcess
783 * is returned to the HqEnt.
785 * 1. Add the HARQ process to the free queue.
786 * Invoked by: scheduler and HARQ processing
788 * @param[in] RgDlHqProc *hqP
789 * @param[in] U8 tbIdx
790 * @param[in] Bool togNdi
795 PUBLIC Void rgSCHDhmRlsHqpTb
797 RgSchDlHqProcCb *hqP,
802 PUBLIC Void rgSCHDhmRlsHqpTb(hqP, tbIdx, togNdi)
803 RgSchDlHqProcCb *hqP;
809 U8 othrTbIdx = tbIdx ^ 1;
811 RgSchCmnDlHqProc *cmnHqDl;
815 RgSchDlLcCb* lcCb = NULLP;
819 TRC2(rgSCHDhmRlsHqpTb)
821 /* Reset all tbInfo values */
826 if (hqP->hqE->ue != NULLP)
828 RgSchUeCb *ueCb = hqP->hqE->ue;
829 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
830 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
831 U8 cqi = dlUe->mimoInfo.cwInfo[0].cqi;
832 /* to get retransmission, decreasing transmission counter */
833 U16 numDlRetx = hqP->tbInfo[0].txCntr-1;
834 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
835 static U32 retxCnt1 = 0;
837 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
838 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
843 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
846 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
849 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
852 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
855 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
856 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
857 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
858 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
859 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
861 retxCnt1 += numDlRetx;
863 #endif /* MAC_SCH_STATS */
864 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
868 hqP->tbInfo[tbIdx].ndi ^= 1;
873 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
875 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
876 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
878 if (lcCb->lcType == CM_LTE_LCH_DTCH)
880 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
882 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
885 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
887 lcCb->qciCb->dlUeCount--;
895 hqP->tbInfo[tbIdx].tbSz = 0;
896 hqP->tbInfo[tbIdx].numLch = 0;
897 hqP->tbInfo[tbIdx].txCntr = 0;
898 /* FOR ACK NACK REP */
899 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
900 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
901 hqP->tbInfo[tbIdx].ackCount = 0;
902 /* pdcch is moved from TbCb to HqCb.
903 This pdcch will be set to NULL when
904 HqCb will be pushed to free list*/
905 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
906 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
907 hqP->tbInfo[tbIdx].nackCount = 0;
908 hqP->tbInfo[tbIdx].dtxCount = 0;
909 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
910 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
912 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
914 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
915 /* Handling msg4 hqProc */
916 if (hqE->msg4Proc == hqP)
918 hqE->msg4Proc = NULLP;
921 /* Add the proc to the free list */
922 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
923 rgSCHDhmHqPAdd2FreeLst(hqP);
927 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
928 * is dangerous and it expects ccchSduProc is the first
929 * DL allocation for a UE, and considering a scenario
930 * of multiple UEs contending and 1 UE per TTI, this
931 * assumption can be wronged, leading to inUse list
932 * corruption. Hence altering this check.
933 * A better approach would be do avoid having this
934 * special handling for ccchSduProc, streamline
935 * it with the usual approach. */
936 if (hqE->ccchSduProc == hqP)
938 hqE->ccchSduProc = NULLP;
939 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
940 * in inUse list, Hence need not to delete from inUse list*/
941 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
943 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
944 rgSCHDhmHqPDelFrmInUseLst(hqP);
948 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
952 /* Add the proc to the free list */
953 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
954 rgSCHDhmHqPAdd2FreeLst(hqP);
959 /* extra:check if other TB is also free for allocation then
960 * add it to FREE List */
961 switch(hqP->tbInfo[othrTbIdx].state)
964 /* Remove the element from the inUse Queue */
965 /* Freeing up the HARQ proc blocked for
966 * indefinite time in case of Retx */
967 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
969 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
970 rgSCHDhmHqPDelFrmInUseLst(hqP);
975 rgEmtcsetNullSubFrm(hqP);
977 /* Add the proc to the free list */
978 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
979 rgSCHDhmHqPAdd2FreeLst(hqP);
981 if (hqE->free.count > 8)
984 printf("Crashing invalid hq count after free \n");
985 printf("Crashing %d \n", *p);
990 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
993 cmnHqDl->spsAction = 0;
994 cmnHqDl->isSpsActv = FALSE;
995 cmnHqDl->isSpsSvcSchd = FALSE;
1000 /* Remove the element from the inUse Queue */
1001 /* Freeing up the HARQ proc blocked for
1002 * indefinite time in case of Retx */
1003 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
1005 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1006 rgSCHDhmHqPDelFrmInUseLst(hqP);
1014 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
1017 } /* rgSCHDhmRlsHqpTb */
1020 * @brief This function releases a HARQ process.
1024 * Function: rgSCHDhmRlsHqProc
1025 * Purpose: This function returns a HARQ process to HARQ Entity
1026 * in the DL direction.
1028 * 1. Add the HARQ process to the free queue.
1029 * Invoked by: scheduler and HARQ processing
1031 * @param[in] RgDlHqProc *hqP
1036 PUBLIC Void rgSCHDhmRlsHqProc
1038 RgSchDlHqProcCb *hqP
1041 PUBLIC Void rgSCHDhmRlsHqProc(hqP)
1042 RgSchDlHqProcCb *hqP;
1046 TRC2(rgSCHDhmRlsHqProc)
1049 #ifdef MAC_SCH_STATS
1050 /* THIS FUNCTION IS NOT CALLED */
1051 if (hqP->hqE->ue != NULLP)
1053 RgSchUeCb *ueCb = hqP->hqE->ue;
1054 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1055 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1056 U8 cqi = dlUe->mimoInfo.cwInfo[0].cqi;
1057 /* to get retransmission, decreasing transmission counter */
1058 U16 numDlRetx = hqP->tbInfo[0].txCntr-1;
1059 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1061 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
1066 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
1069 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
1072 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
1075 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
1078 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
1079 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
1080 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
1081 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
1082 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
1084 #endif /* MAC_SCH_STATS */
1086 hqP->subFrm = NULLP;
1088 rgEmtcsetNullSubFrm(hqP);
1090 rgSCHDhmHqPDelFrmInUseLst(hqP);
1091 rgSCHDhmHqPAdd2FreeLst(hqP);
1097 } /* rgSCHDhmRlsHqProc */
1101 * @brief This function gets HARQ process with the given ID.
1105 * Function: rgSCHDhmGetHqProcFrmId
1106 * Purpose: This function returns the HARQ process with the given ID.
1109 * @param[in] RgSchUeCb *ue
1111 * @param[in] RgDlHqProc **hqP
1113 * -# ROK if successful
1114 * -# RFAILED otherwise
1118 PUBLIC S16 rgSCHDhmGetHqProcFrmId
1123 RgSchDlHqProcCb **hqP
1126 PUBLIC S16 rgSCHDhmGetHqProcFrmId(cell, ue, idx, hqP)
1130 RgSchDlHqProcCb **hqP;
1134 TRC2(rgSCHDhmGetHqProcFrmId)
1136 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1137 /* Pick the proc based on the index provided */
1138 *hqP = &(hqE->procs[idx]);
1141 } /* rgSCHDhmGetHqProcFrmId */
1144 * @brief This function gets SPS HARQ process from the given time
1148 * Function: rgSCHDhmSpsDlGetHqProc
1149 * Purpose: This function returns the SPS HARQ process for the given time
1151 * @param[in] RgSchUeCb *ue
1152 * @param[in] CmLteTimingInfo timingInfo
1153 * @return RgSchDlHqProcCb control block
1157 PUBLIC RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc
1161 CmLteTimingInfo timingInfo
1164 PUBLIC RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(cell, ue, timingInfo)
1167 CmLteTimingInfo timingInfo;
1172 RgSchDlHqProcCb *hqProc = NULLP;
1173 CmLList *tmp = NULLP;
1175 TRC2(rgSCHDhmSpsDlGetHqProc);
1177 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1179 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1183 /* No Harq Process available in the free queue. */
1187 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1188 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1191 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1193 /* If the HARQ process is in the free list, retrieve the process */
1194 while (hqProc->procId != idx)
1196 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1201 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1206 /* No Harq Process available in the free queue. */
1210 hqProc->tbInfo[0].timingInfo = timingInfo;
1211 hqProc->tbInfo[1].timingInfo = timingInfo;
1213 /* Remove the element from the free Queue */
1214 //cmLListDelFrm(&hqE->free, tmp);
1215 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1217 /* Add the element into the inUse Queue as well */
1218 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1219 rgSCHDhmHqPAdd2InUseLst(hqProc);
1222 rgSCHLaaResetDlHqProcCb(hqProc);
1226 } /* rgSCHDhmSpsDlGetHqProc */
1227 #endif /* LTEMAC_SPS */
1230 /** * @brief Handler for handling TA.
1234 * Function : rgSCHDhmFdbkIndHndlTa
1236 * This function handles the TA state and values based on the
1237 * feedback indication received.
1239 * @param[in] RgSchDlHqProcCb *hqP
1240 * @param[in] U8 tbIdx
1241 * @param[in] U8 fdbk
1246 PRIVATE Void rgSCHDhmFdbkIndHndlTa
1248 RgSchDlHqProcCb *hqP,
1251 Bool maxHqRetxReached
1254 PRIVATE Void rgSCHDhmFdbkIndHndlTa(hqP, tbIdx, fdbk,maxHqRetxReached)
1255 RgSchDlHqProcCb *hqP;
1258 Bool maxHqRetxReached;
1264 TRC2(rgSCHDhmFdbkIndHndlTa)
1266 ueCb = hqP->hqE->ue;
1271 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1272 hqP->tbInfo[tbIdx].taSnt = FALSE;
1273 /* To prevent duplicate inserts of ueCb into TA list */
1274 if (ueCb->taLnk.node == NULLP)
1276 ueCb->taLnk.node = (PTR)ueCb;
1277 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1282 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Trying to add CRNTI:%d into TA"
1283 "ACK List twice", ueCb->ueId);
1289 /* If Ta was sent and its the final NACK, then reset only the
1290 * taState to IDLE and not the value */
1291 /* Changed handling in case maxhqretx is reached for TA */
1292 if(TRUE == maxHqRetxReached)
1294 hqP->tbInfo[tbIdx].taSnt = FALSE;
1295 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1297 rgSCHUtlReTxTa(cell, ueCb);
1298 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
1299 "Nack Rcvd for TA. Max Tries Attempted");
1303 /* If Ta was sent and its the final NACK, then reset only the
1304 * taState to IDLE and not the value */
1305 if(TRUE == maxHqRetxReached)
1307 hqP->tbInfo[tbIdx].taSnt = FALSE;
1308 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1310 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1311 * issue for VoLTE call */
1312 rgSCHUtlDlTARpt(cell, ueCb);
1321 } /* rgSCHDhmFdbkIndHndlTa */
1323 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1324 /** * @brief Handler for scheduling TA.
1328 * Function : rgSCHDhmShcdTa
1330 * This function is called by scheduler when resource allocation
1331 * for TA transmission is done.
1333 * @param[in] RgSchUeCb *ue
1334 * @param[out] RgSchDlHqTbCb *tbInfo
1339 PUBLIC Void rgSCHDhmSchdTa
1342 RgSchDlHqTbCb *tbInfo
1345 PUBLIC Void rgSCHDhmSchdTa(ueCb, tbInfo)
1347 RgSchDlHqTbCb *tbInfo;
1351 TRC2(rgSCHDhmSchdTa)
1353 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1354 ueCb->dl.taCb.numRemSf = 2;
1355 tbInfo->schdTa.pres = PRSNT_NODEF;
1356 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1359 } /* rgSCHDhmSchdTa */
1362 /** * @brief Handler for fetching Harq Proc given the feeback information.
1366 * Function : rgSCHDhmHqProcByFdbkTime
1368 * This function shall fetch all the harq proc having the feedback
1369 * timing information.
1371 * @param[in] RgSchDlHqEnt *hqE
1372 * @param[in] CmLteTimingInfo timeInfo
1373 * @param[in] Bool *isMsg4
1374 * @param[out] RgSchDlHqProcCb **hqPrcs
1375 * @param[out] U8 *numTbs
1376 * @param[out] S8 *tbStrtIdx
1377 * @param[out] U8 *cntHqPrcs
1381 PRIVATE S16 rgSCHDhmHqProcByFdbkTime
1384 CmLteTimingInfo timeInfo,
1386 RgSchDlHqProcCb **hqPrcs,
1393 PRIVATE S16 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, isMsg4, hqPrcs,
1394 numTbs, tbStrtIdx, cntHqPrcs)
1396 CmLteTimingInfo timeInfo;
1398 RgSchDlHqProcCb **hqPrcs;
1405 RgSchDlHqTbCb *tbCb;
1406 RgSchDlHqProcCb *hqP;
1407 CmLteTimingInfo schdSfTime;
1408 RgSchTddDlAscSetIdxK ascIdx;
1419 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1422 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1423 tbStrtIdx[*cntHqPrcs] = 0;
1424 numTbs[*cntHqPrcs] = 1;
1429 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1430 noFdbks = ascIdx.numFdbkSubfrms;
1432 for(idx=0; idx<noFdbks; idx++)
1434 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1435 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1436 * serving the purpose */
1437 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1438 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1439 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1443 hqP = (RgSchDlHqProcCb*)node->node;
1446 numTbs[*cntHqPrcs] = 0;
1447 tbStrtIdx[*cntHqPrcs] = -1;
1448 for (i = 0; i < 2; i++)
1450 /* Extra:check which TB is waiting for feedback */
1451 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1453 if (tbStrtIdx[*cntHqPrcs] == -1)
1455 tbStrtIdx[*cntHqPrcs] = i;
1457 numTbs[*cntHqPrcs]++;
1460 if (numTbs[*cntHqPrcs] > 0)
1462 hqPrcs[*cntHqPrcs] = hqP;
1467 /* AN REP Hq Procs */
1468 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1471 tbCb = (RgSchDlHqTbCb *)(node->node);
1474 numTbs[*cntHqPrcs] = 0;
1475 tbStrtIdx[*cntHqPrcs] = -1;
1476 for (i = 0; i < 2; i++)
1478 /* Extra:check which TB is waiting for feedback */
1479 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1481 if (tbStrtIdx[*cntHqPrcs] == -1)
1483 tbStrtIdx[*cntHqPrcs] = i;
1485 numTbs[*cntHqPrcs]++;
1488 if (numTbs[*cntHqPrcs] == 2)
1492 if (numTbs[*cntHqPrcs] > 0)
1494 hqPrcs[*cntHqPrcs] = hqP;
1506 /** * @brief Handler for fetching Harq Proc given the timming information.
1510 * Function : rgSCHDhmHqProcByTime
1512 * This function shall fetch the harq proc using the timing information.
1514 * @param[in] RgSchDlHqEnt *hqE
1515 * @param[in] CmLteTimingInfo timeInfo
1516 * @param[in] Bool *isMsg4
1517 * @param[out] U8 *numTbs
1518 * @param[out] S8 *tbStrtIdx
1519 * @return RgSchDlHqProcCb*
1520 * -# RgSchDlHqProcCb*
1524 PUBLIC RgSchDlHqProcCb *rgSCHDhmHqProcByTime
1527 CmLteTimingInfo timeInfo,
1532 PUBLIC RgSchDlHqProcCb *rgSCHDhmHqProcByTime(hqE, timeInfo,
1535 CmLteTimingInfo timeInfo;
1542 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1545 return (hqE->msg4Proc);
1553 /** * @brief Handler for handling the harq transaction failure.
1557 * Function : rgSCHDhmHqTbTrnsFail
1559 * This function handled the harq TB transaction failure :
1560 * - If retries have not reached maximum, add to the reTx Q.
1561 * - else do error recovery.
1563 * @param[in] RgSchCellCb *cell
1564 * @param[in] RgSchDlHqProcCb *hqP
1565 * @param[in] U8 tbCnt
1566 * @param[out] Bool *isMaxRetx
1572 PUBLIC Void rgSCHDhmHqTbTrnsFail
1575 RgSchDlHqProcCb *hqP,
1580 PUBLIC Void rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, isMaxRetx)
1582 RgSchDlHqProcCb *hqP;
1590 TRC2(rgSCHDhmHqTbTrnsFail)
1594 /* Fetch the maximum number of harq transmissions */
1595 if (hqE->msg4Proc == hqP)
1598 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1600 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1601 "rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1602 hqP->hqE->raCb->tmpCrnti);
1603 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1607 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1611 maxHqTx = hqE->maxHqTx;
1614 #ifdef MAC_SCH_STATS
1615 if (hqE->ue != NULLP)
1617 RgSchUeCb *ueCb = hqE->ue;
1618 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1619 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1620 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1621 static U32 retxCnt = 0;
1625 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1627 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1628 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1630 #endif /* MAC_SCH_STATS */
1632 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1633 /* Reset the PDCCH reference */
1635 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1637 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1639 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1642 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1643 * for the UE. Addtion to the retransmission queue will be done on
1644 * HARQ RTT timer expiry.--*/
1645 switch(hqP->tbInfo[tbCnt ^ 1].state)
1648 /*As the first TB is ACKED we have not started HARQ RTT for the
1649 * HqP, so start it here.*/
1650 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1651 rgSCHDhmHqPDelFrmInUseLst(hqP);
1653 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1656 /* Integration fix */
1657 /* Setting cntrRetxAllocFail to MAX value here */
1658 /* Since the hqP entry is already deleted from inUse list of HqEntity
1659 setting the value here will ensure the entry is not deleted
1660 again during release harq proc */
1661 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1662 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1664 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1665 if (hqP->tbInfo[1].txCntr)
1667 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1673 /*As the first TB is NACKED we have already started HARQ RTT for the
1674 * HqP, so dont start it here, just delete from in use queue.*/
1675 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1676 rgSCHDhmHqPDelFrmInUseLst(hqP);
1679 /*As this is the first TB to be fed back and is NACKED start
1680 * the HARQ RTT here.*/
1682 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1688 /* extra:check if already removed as part of other TB processing
1689 * then donot remove from InUse Q */
1690 /* Check if other TB is not waiting for feedback.
1691 * Makinf sure hqP is present in inUse Queue until
1692 * it is fedback for all its TBs */
1693 switch(hqP->tbInfo[tbCnt ^ 1].state)
1696 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1697 if(hqE->msg4Proc != hqP)
1699 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1700 rgSCHDhmHqPDelFrmInUseLst(hqP);
1702 /* Retransmission needs to be done. Add to the scheduler Q */
1703 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1706 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1707 if(hqE->msg4Proc != hqP)
1709 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1710 rgSCHDhmHqPDelFrmInUseLst(hqP);
1714 /* Retransmission needs to be done. Add to the scheduler Q */
1716 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1724 /* Failure Notification */
1725 if (hqE->msg4Proc == hqP)
1727 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1728 rgNumMsg4FailMaxRetx++;
1730 hqE->cell->tenbStats->sch.msg4Fail ++;
1733 /* Perform RAM MSG4 done processing */
1734 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1735 "rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1736 hqP->hqE->raCb->tmpCrnti);
1737 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1741 /* Release the Harq Proc */
1742 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1748 } /* rgSCHDhmHqTbTrnsFail */
1750 PUBLIC U32 rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1751 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1754 /** * @brief Function to decode the position of HarqFb for M=1.
1758 * Function : rgSchGetHqFdbkPosForM1
1760 * @param[in] RgSchUeCb *ue,
1761 * @param[in] RgSchDlHqProcCb *hqP,
1762 * @param[in] U8 *isAck,
1763 * @param[in] RgTfuHqInfo *fdbk,
1764 * @param[in] U8 tbIdx,
1765 * @param[in] RgSchTddANInfo *anInfo;
1769 PRIVATE Void rgSchGetHqFdbkPosForM1
1772 RgSchDlHqProcCb *hqP,
1776 RgSchTddANInfo *anInfo
1779 PRIVATE Void rgSchGetHqFdbkPosForM1(ue,hqP,isAck,fdbk,tbIdx,anInfo)
1781 RgSchDlHqProcCb *hqP;
1785 RgSchTddANInfo *anInfo;
1790 /* handle pusch and pucch cases */
1791 /* PUSCH:: Fdbks are in the increasing order
1792 * of servCellIdx as per 36.212 section 5.2.26*/
1793 switch(ue->f1bCsAVal)
1795 case RG_SCH_A_VAL_2:
1797 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1799 *isAck = fdbk->isAck[1];/*SCell*/
1803 *isAck = fdbk->isAck[0];/*PCell*/
1807 case RG_SCH_A_VAL_3:
1809 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1811 U8 cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1812 hqP->hqE->cell->cellId,
1815 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1816 {/*SCell - mimo mode*/
1817 if(TRUE == fdbk->isPusch)
1819 *isAck = fdbk->isAck[tbIdx + 1];
1823 *isAck = fdbk->isAck[tbIdx];
1827 {/*SCell - siso mode*/
1828 *isAck = fdbk->isAck[2];
1832 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1833 {/*Primary Cell - mimo mode*/
1834 *isAck = fdbk->isAck[tbIdx];
1837 {/*Primary Cell - siso mode*/
1838 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1840 /* If fdbk is on PUSCH but its not an SPS occasion*/
1841 *isAck = fdbk->isAck[0];
1845 /* If fdbk is on PUCCH or its an SPS occasion*/
1846 *isAck = fdbk->isAck[2];
1852 case RG_SCH_A_VAL_4:
1854 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1856 *isAck = fdbk->isAck[tbIdx + 2];
1860 *isAck = fdbk->isAck[tbIdx];
1869 }/* End of rgSchGetHqFdbkPosForM1 */
1871 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1875 * Function : rgSchGetHqFdbkPosForM234
1877 * @param[in] RgSchUeCb *ue,
1878 * @param[in] RgSchDlHqProcCb *hqP,
1879 * @param[in] U8 *isAck,
1880 * @param[in] RgTfuHqInfo *fdbk,
1881 * @param[in] U8 tbIdx,
1882 * @param[in] RgSchTddANInfo *anInfo;
1883 * @param[in] CmLteTimingInfo timeInfo;
1887 PRIVATE Void rgSchGetHqFdbkPosForM234
1890 RgSchDlHqProcCb *hqP,
1894 RgSchTddANInfo *anInfo,
1896 CmLteTimingInfo timeInfo
1899 PRIVATE Void rgSchGetHqFdbkPosForM234(ue,hqP,isAck,fdbk,tbIdx,anInfo,M,timeInfo)
1901 RgSchDlHqProcCb *hqP;
1905 RgSchTddANInfo *anInfo;
1907 CmLteTimingInfo timeInfo;
1912 RgSchTddANInfo *pCellAnInfo;
1917 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1918 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1920 if(TRUE == fdbk->isPusch)
1924 if (anInfo->wUlDai == 3)
1926 incr = anInfo->wUlDai;
1932 if(1 == anInfo->ulDai)
1934 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1935 hqP->tbInfo[tbIdx].tbIdx + incr;
1939 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1944 if(1 == anInfo->ulDai)
1946 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1948 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1952 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1957 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1965 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1966 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1972 /* SPS occasion feedback in case of M > 2 will
1973 * be always present in the index 0*/
1975 if(hqP->spsN1PucchRes.pres == TRUE)
1976 {/* SPS occasion hq proc */
1980 if((NULLP != pCellAnInfo) &&
1981 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1983 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1985 {/* NO SPS occasion was present in the bundle*/
1986 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1991 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1995 *isAck = fdbk->isAck[fdbkIdx];
1997 static RgSchDlHqProcCb *temp = NULLP;
1998 if (temp != hqP->tbInfo[tbIdx].hqP)
2000 statsCnt = statsCnt % 10000;
2001 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
2002 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
2003 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot;
2004 dlHqStats[statsCnt].ack = *isAck;
2005 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
2006 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;;
2008 dlHqStats[statsCnt].ulDai = incr;
2009 if(TRUE == fdbk->isPusch)
2011 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
2015 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
2019 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
2020 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
2021 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
2022 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
2023 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
2024 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
2025 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
2026 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
2029 temp = hqP->tbInfo[tbIdx].hqP;
2034 }/*rgSchGetHqFdbkPosForM234*/
2038 * @brief Handler for HARQ feedback received for DL transmission.
2042 * Function : rgSCHDhmHqFdbkInd
2044 * This function shall act on the feedback received from TOM for DL
2045 * transmission. If the feedback for msg4 is final (after max transmissions
2046 * or ACK) inform RAM that Msg4 transmission is done.
2049 * @param[in] Void *cb
2050 * @param[in] U8 cbType
2051 * @param[in] RgSchCellCb cellCb
2052 * @param[in] CmLteTimingInfo timeInfo
2053 * @param[in] TfuHqInfo *fdbk
2054 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2055 * @param[in] RgSchErrInfo *err
2061 PUBLIC S16 rgSCHDhmHqFdbkInd
2065 RgSchCellCb *cellCb,
2066 CmLteTimingInfo timeInfo,
2068 RgInfRlsHqInfo *rlsHqBufs,
2072 PUBLIC S16 rgSCHDhmHqFdbkInd(cb, cbType, cellCb, timeInfo, fdbk, rlsHqBufs, err)
2075 RgSchCellCb *cellCb;
2076 CmLteTimingInfo timeInfo;
2078 RgInfRlsHqInfo *rlsHqBufs;
2082 RgSchCellCb *sCell = NULLP;
2084 /*ccpu00127339 - MOD - change to avoid the crash*/
2085 RgSchUeCb *ue = NULLP;
2087 Bool isMsg4 = FALSE;
2088 RgSchRaCb *raCb = NULLP;
2090 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
2091 * given feedback at a time */
2092 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
2093 U8 numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
2094 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
2097 RgSchTddANInfo *anInfo = NULLP;
2100 RgrTddAckNackMode ackNackMode;
2102 RgSchDlSf *nxtDlsf = NULLP;
2103 /* U8 rcvCnt = 0; */
2104 CmLteTimingInfo nxtfrm = {0,0};
2106 Bool maxHqRetxReached;
2108 Bool hasRelPdcch = FALSE;
2111 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2112 RgSchTddDlAscSetIdxK ascIdx;
2116 #ifdef LTEMAC_SPS_AN_MUX
2117 Bool isPusch = FALSE;
2120 /* Subframes in which transmissions are scheduled and whose feedback can come
2121 * in this subframe. Used only for Multiplexing mode */
2122 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
2123 #ifdef RGSCH_SPS_STATS
2124 RgSchCmnDlHqProc *cmnHqDl;
2128 U8 sCellActCePres = 0;
2130 /* LTEMAC_SPS_AN_MUX*/
2131 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
2132 TRC2(rgSCHDhmHqFdbkInd)
2134 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
2136 raCb = (RgSchRaCb *)(cb);
2137 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
2139 /* ccpu00139061 Fix */
2140 rnti = raCb->tmpCrnti;
2144 ue = (RgSchUeCb *)(cb);
2145 ackNackMode = ue->dl.ackNackMode;
2146 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
2148 #ifdef LTEMAC_SPS_AN_MUX
2149 isPusch = fdbk->isPusch;
2153 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
2160 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2161 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
2162 noFdbks = ascIdx.numFdbkSubfrms;
2164 #ifdef LTEMAC_SPS_AN_MUX
2165 /* Calculate the subframe time at which transmissions should have happened to
2166 * receive feedback in this subframe */
2167 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2169 for(idx=0; idx<noFdbks; idx++)
2171 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
2172 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
2173 * serving the purpose */
2174 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
2179 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
2180 tbStrtIdx, &hqCnt,hqE->cell);
2181 /* Fetch the harqProc from the inUse list */
2183 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
2187 err->errType = RGSCHERR_DHM_FDBK_IND;
2188 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2192 /* ccpu00147469 : This code is moved below as here this code always try to
2193 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
2197 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
2199 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
2205 #ifdef LTEMAC_SPS_AN_MUX
2206 /* Check if feedback came on configured UL SPS grant in Muxing mode */
2207 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
2211 /* Pick the valid feedbacks out of M feedbacks */
2212 for(idx=0; idx<noFdbks; idx++)
2214 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
2215 * and no release pdcch is sent in prevTime */
2216 /* TODO: SPS_TDD: Check this while testing */
2217 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
2218 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
2219 schdSfTime[idx])) &&
2220 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
2222 /* Discard the feedback which is corresponding to a subframe in
2223 * which no DL transmission took place */
2225 while(tmpIdx < noFdbks)
2227 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2228 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2234 } /* end of for loop */
2235 } /* end of configured UL SPS grant check */
2247 for(idx=0;idx < hqCnt; idx++)
2249 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
2253 U8 servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
2254 hqPrcs[idx]->hqE->cell->cellId,ue);
2256 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
2260 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
2262 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
2266 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
2267 "Ack Rcvd. No Ack/Nack feedback available \n"));
2272 sCell = hqPrcs[idx]->hqE->cell;
2273 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2274 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2275 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2277 /* Fix : syed MultiUe per TTI crash in TA List. */
2279 maxHqRetxReached = FALSE;
2280 /* Remove the harq process from the subframe */
2281 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2285 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2288 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2290 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2291 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2293 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2297 /* TODO: review for TM4 and CA interaction */
2298 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2300 isAck = fdbk->isAck[!tbCnt];
2304 isAck = fdbk->isAck[tbCnt];
2313 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2317 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2323 /* revanth tweakin AN PUSCH to ACK always */
2324 if (hqPrcs[idx]->isPuschFdbk)
2330 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2331 if(cellCb->ulDlCfgIdx != 5)
2333 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2334 cellCb, sf, &nxtDlsf, &nxtfrm);
2336 /* Keep a tab on how many ACKs or NACKs we have received */
2337 if (isAck == TFU_HQFDB_ACK)
2339 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2340 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2342 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2343 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2345 /* Do not update the Ul Trans Time in case of raCb */
2348 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2350 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2354 else if (isAck == TFU_HQFDB_NACK)
2356 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2357 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2359 sCell->tenbStats->sch.dlNack[tbCnt]\
2360 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2361 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2362 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2364 /* Do not update the Ul Trans Time in case of raCb */
2367 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2369 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2370 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2374 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2376 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2382 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2384 sCell->tenbStats->sch.dlDtx[tbCnt]\
2385 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2388 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2392 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2394 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2399 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2401 if(isAck == TFU_HQFDB_ACK)
2403 gSCellTb1AckCount++;
2404 gSCellTb2AckCount++;
2405 }else if(isAck == TFU_HQFDB_NACK)
2407 gSCellTb1NackCount++;
2408 gSCellTb2NackCount++;
2411 gSCellTb1DtxCount++;
2412 gSCellTb2DtxCount++;
2417 if(isAck == TFU_HQFDB_ACK)
2419 gPCellTb1AckCount++;
2420 gPCellTb2AckCount++;
2421 }else if(isAck == TFU_HQFDB_NACK)
2423 gPCellTb1NackCount++;
2424 gPCellTb2NackCount++;
2427 gPCellTb1DtxCount++;
2428 gPCellTb2DtxCount++;
2432 /* Check if this is repeating UE */
2433 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2435 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2436 /* Check if last repetition */
2437 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2439 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2440 /* Update feedback time for this hqP TB so that
2441 * next subframe its picked up */
2442 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2444 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2445 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2449 /* For a repeating UE take the decision here */
2450 /* For a repeating UE take the decision here */
2451 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2452 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2454 isAck = TFU_HQFDB_ACK;
2456 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2457 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2459 isAck = TFU_HQFDB_DTX;
2463 isAck = TFU_HQFDB_NACK;
2465 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2469 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2472 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2473 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2474 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2477 /* ACK or NACK received for SPS ACTV PDCCH
2478 * Hence consider SPS ACTVN PDCCH received successfully */
2479 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2482 if(TFU_HQFDB_ACK == isAck)
2489 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2491 /* Inform Random Access Module regarding the ack received */
2494 /*RRC Connection Setup failure issue where RRC connection
2495 * setup was not reaching UE due to message 4 HARQ failure */
2496 #ifdef XEON_SPECIFIC_CHANGES
2497 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2499 rgSCHRamMsg4Done(cellCb, raCb);
2502 else /*ccpu00114124- HARQ Release for Msg4 */
2505 /*Update feedback history for every Tx/Retx */
2506 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2508 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2509 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2511 /* Store activation CE presence as it is required later to start
2512 *activation delay timer */
2513 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2515 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2521 /* If this Msg4 DTX, there will be
2522 * no DlHqProc as it has its own HarqProc */
2525 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2526 maxHqRetxReached = hqRls;
2528 if ((isMsg4 == FALSE))
2530 /*Update feedback history for every Tx/Retx */
2531 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2534 if (isMsg4 == FALSE)
2536 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2537 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2544 /* MS_WORKAROUND: to increase Harq Fail Counter .
2545 The status field is required for tracking the number of harq faliures at MAC*/
2548 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2549 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2553 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2554 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2556 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2557 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2558 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2562 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2564 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2567 /* Handle Scell activation */
2568 if (TRUE == sCellActCePres)
2570 /* Primary Cellcb needs to be retrived
2571 * if the feedback is coming on pusch of
2572 * sec cell. THis needs to be considered
2574 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2580 hqPrcs[idx]->cwSwpEnabled = FALSE;
2582 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2584 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2585 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2586 hqPrcs[idx]->procId;
2587 rlsHqBufs->numUes++;
2590 hqPrcs[idx]->isPuschFdbk = 0;
2595 /*it is possible for some TDD configurations (like TDD cfg 5)
2596 * to have multiple feedback for 13 subframes before. It is
2597 * possible in such a case to have a release sent after data
2598 * thus running into a situation where we are receiving feedback
2599 * for both data and relese pdcch
2602 if ( (hqCnt == 0) ||
2603 (hasRelPdcch && rcvCnt > hqCnt)
2606 if (ue && hasRelPdcch)
2608 /* Bool found = FALSE; */
2610 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2620 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2621 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2623 CmLteTimingInfo txTime;
2628 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2630 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2634 for(itr=0; itr< maxFdbks; itr++)
2637 /* Handling the case of only SPS release pdcch
2638 * and no other scheduling in both the serving cells
2640 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2641 {/* Using the sorted K table */
2642 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2643 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2647 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2648 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2651 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2654 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2657 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2659 isAck = fdbk->isAck[0];
2662 isAck = fdbk->isAck[2];
2666 /* M > 1 same below logic apply.
2667 If SPS occasion and rel pdcch is present
2668 SPS occasion after SPS release cannot
2673 isAck = fdbk->isAck[itr];
2676 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2678 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2679 /* Remove release PDCCH from the subframe */
2680 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2681 sf->relPdcch = NULLP;
2691 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2692 /* Remove release PDCCH from the subframe */
2693 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2694 sf->relPdcch = NULLP;
2696 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2699 if ( found == FALSE )
2701 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2702 RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,"CRNTI:%d"
2703 " NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2704 ue->ueId,timeInfo.sfn, timeInfo.slot);
2705 err->errType = RGSCHERR_DHM_FDBK_IND;
2706 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2711 #endif /* LTEMAC_SPS */
2712 /* Initialise the Ack/Nack feedback */
2713 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2714 scheduling. So added a condition !isMsg4 to avoid calling the function
2715 rgSCHUtlInitUeANFdbkInfo*/
2716 if((ue) && (!anUpd) && (!isMsg4))
2719 /* TODO:: Initi the anInfo all the serving cells */
2720 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2722 if(ue->cellInfo[idx])
2724 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2725 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2726 * else don't do anything. basically continue for next serving
2730 rgSCHUtlInitUeANFdbkInfo(anInfo);
2735 rgSCHUtlInitUeANFdbkInfo(anInfo);
2741 //#endif /* LTEMAC_SPS */
2744 /** * @brief Handler for HARQ feedback received for DL transmission.
2748 * Function : rgSCHDhmPrcFdbkForTb
2750 * Process Hq Prc Fdbk for a TB
2752 * @param[in] RgSchCellCb *cell
2753 * @param[in] RgTfuHarqAckIndInfo *fdbk
2754 * @param[in] RgSchErrInfo *err
2760 PUBLIC S16 rgSCHDhmPrcFdbkForTb
2764 RgSchDlHqProcCb *hqP,
2769 CmLteTimingInfo timingInfo,
2771 RgInfRlsHqInfo *rlsHqBufs,
2775 PUBLIC S16 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt, timingInfo, isAck, rlsHqBufs, err)
2778 RgSchDlHqProcCb *hqP;
2783 CmLteTimingInfo timingInfo;
2785 RgInfRlsHqInfo *rlsHqBufs;
2790 Inst inst = cell->instIdx;
2792 #ifdef RGSCH_SPS_STATS
2793 RgSchCmnDlHqProc *cmnHqDl;
2796 RgSchRaCb *raCb = NULLP;
2798 Bool hqFreed =FALSE;
2799 Bool maxHqRetxReached = FALSE;
2800 RgSchCmnDlUe *ueDl = NULLP;
2801 RgSchCellCb *sCell = hqP->hqE->cell;
2803 RgSchEmtcDlSf *emtcSf;
2804 CmLteTimingInfo frm = timingInfo;
2807 TRC2(rgSCHDhmPrcFdbkForTb)
2810 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2813 /* Fix : syed MultiUe per TTI crash in TA List. */
2814 maxHqRetxReached = FALSE;
2816 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2817 * TODO: Need to enhance this in case of TM4 testing,
2818 * when cwSwap flag is considered. */
2820 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2821 tbCnt=%d , isAck=%d",tbCnt,isAck));
2822 if (isAck == TFU_HQFDB_ACK)
2824 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2826 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2827 /* Do not update the Ul Trans Time in case of raCb */
2830 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2832 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2838 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2839 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2844 else if (isAck == TFU_HQFDB_NACK)
2846 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2847 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2848 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2849 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2850 /* Do not update the Ul Trans Time in case of raCb */
2853 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2854 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2856 sCell->tenbStats->sch.dlNack[tbCnt]\
2857 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2864 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2866 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2867 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2870 /* Added Dl TB count for NACKED data*/
2872 if(hqP->tbInfo[tbCnt].txCntr == 1)
2874 cell->dlUlTbCnt.tbTransDlFaulty++;
2880 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2881 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2882 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2885 sCell->tenbStats->sch.dlDtx[tbCnt]\
2886 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2889 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2894 /* Added Dl TB count for DTXED data*/
2896 if(hqP->tbInfo[tbCnt].txCntr == 1)
2898 cell->dlUlTbCnt.tbTransDlFaulty++;
2903 /* Check if this is repeating UE */
2904 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2906 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2913 /* For a Normal UE take the decision here */
2914 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2916 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2919 /* Process either the ACK received or max retries have occurred */
2920 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2921 if (TFU_HQFDB_ACK == isAck)
2925 /* SR_RACH_STATS : MSG4 ACK*/
2930 raCb = rgSCHDbmGetRaCb(cell, rnti);
2932 RGSCHDBGINFO(cell->instIdx,
2933 (rgSchPBuf(cell->instIdx), "Ack Rcvd. FdbkInd for Msg4Done\n"));
2934 /* Inform Random Access Module regarding the ack received */
2937 /*RRC Connection Setup failure issue where RRC connection
2938 * setup was not reaching UE due to message 4 HARQ failure */
2939 printf("\nMSG4 Ack ,calling rgSCHRamMsg4Done\n");
2940 ret = rgSCHRamMsg4Done(cell, raCb);
2945 printf("\nraCb is NULLP\n");
2948 else /*ccpu00114124- HARQ Release for Msg4 */
2950 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2951 /* Push this harq process back to the free queue */
2952 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2954 if(hqP->tbInfo[tbCnt].txCntr == 1)
2956 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2959 RGSCH_NULL_CHECK(cell->instIdx, ue);
2960 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2961 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2970 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2971 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2973 if(hqP->tbInfo[tbCnt].txCntr == 1)
2975 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2978 RGSCH_NULL_CHECK(cell->instIdx, ue);
2979 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2983 #ifdef XEON_SPECIFIC_CHANGES
2984 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2988 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2989 maxHqRetxReached = hqRls;
2995 /* MS_WORKAROUND: to increase Harq Fail Counter .
2996 The status field is required for tracking the number of harq faliures at MAC*/
2999 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3000 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
3003 else if(maxHqRetxReached)
3005 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
3006 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3007 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
3012 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3013 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
3015 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
3016 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
3017 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
3021 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
3023 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
3026 } /* rgSCHDhmPrcFdbkForTb */
3027 /** * @brief Function to decode the position of HarqFb for eachCell.
3031 * Function : rgSchGetHqFdbkPos
3033 * @param[in] RgSchCellCb *cell,
3034 * @param[in] RgSchUeCb *ue,
3035 * @param[in] RgSchDlHqProcCb *hqP,
3036 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
3037 * @param[in] Bool *isAck,
3038 * @param[in] RgTfuHqInfo *fdbk,
3042 PUBLIC Void rgSchGetHqFdbkPos
3046 RgSchDlHqProcCb *hqP,
3047 RgrSchFrmt1b3TypEnum uciFrmtTyp,
3052 PUBLIC Void rgSchGetHqFdbkPos(cell,ue,hqP,uciFrmtTyp,isAck,fdbk)
3055 RgSchDlHqProcCb *hqP;
3056 RgrSchFrmt1b3TypEnum uciFrmtTyp;
3061 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
3063 isAck[0] = fdbk->isAck[0];
3064 isAck[1] = fdbk->isAck[1];
3068 /* LAA Making all ack for LAA CELL */
3069 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
3079 /* PUSCH:: Fdbks are in the increasing order
3080 * of servCellIdx as per 36.212 section 5.2.26*/
3081 switch(ue->f1bCsAVal)
3083 case RG_SCH_A_VAL_2:
3085 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3087 isAck[0] = fdbk->isAck[1];/*SCell*/
3088 isAck[1] = fdbk->isAck[1];/*SCell*/
3092 isAck[0] = fdbk->isAck[0];/*PCell*/
3093 isAck[1] = fdbk->isAck[0];/*PCell*/
3097 case RG_SCH_A_VAL_3:
3099 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3102 U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
3103 hqP->hqE->cell->cellId,
3106 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
3108 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
3110 { /* Sec cell is in mimo mode */
3111 /* use 0 and 1 for sec in case of pucch
3112 * and 1 and 2 in case of PUSCH as the primary cell is in
3113 * siso case as A =3 */
3116 isAck[0] = fdbk->isAck[0];
3117 isAck[1] = fdbk->isAck[1];
3119 {/* PUSCH as per 36.212 serction 5.2.26*/
3120 isAck[0] = fdbk->isAck[1];
3121 isAck[1] = fdbk->isAck[2];
3124 {/* sec cell is in siso */
3125 isAck[0] = fdbk->isAck[2];
3129 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3130 {/* primay cell is in mimo
3132 isAck[0] = fdbk->isAck[0];
3133 isAck[1] = fdbk->isAck[1];
3138 isAck[0] = fdbk->isAck[2];
3140 {/* PUSCH as per 36.212 serction 5.2.26*/
3141 isAck[0] = fdbk->isAck[0];
3147 case RG_SCH_A_VAL_4:
3149 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3151 isAck[0] = fdbk->isAck[2];
3152 isAck[1] = fdbk->isAck[3];
3155 if(isAck[0] == TFU_HQFDB_ACK)
3157 gSCellTb1AckCount++;
3158 }else if(isAck[0] == TFU_HQFDB_NACK)
3160 gSCellTb1NackCount++;
3163 gSCellTb1DtxCount++;
3166 if(isAck[1] == TFU_HQFDB_ACK)
3168 gSCellTb2AckCount++;
3169 }else if(isAck[1] == TFU_HQFDB_NACK)
3171 gSCellTb2NackCount++;
3174 gSCellTb2DtxCount++;
3182 isAck[0] = fdbk->isAck[0];
3183 isAck[1] = fdbk->isAck[1];
3186 if(isAck[0] == TFU_HQFDB_ACK)
3188 gPCellTb1AckCount++;
3189 }else if(isAck[0] == TFU_HQFDB_NACK)
3191 gPCellTb1NackCount++;
3194 gPCellTb1DtxCount++;
3197 if(isAck[1] == TFU_HQFDB_ACK)
3199 gPCellTb2AckCount++;
3200 }else if(isAck[1] == TFU_HQFDB_NACK)
3202 gPCellTb2NackCount++;
3205 gPCellTb2DtxCount++;
3220 }/* End of rgSchGetHqFdbkPos */
3223 PUBLIC Void rgSchGetHqFdbkPosFormat3
3225 RgSchDlHqProcCb *hqP,
3230 PUBLIC Void rgSchGetHqFdbkPosFormat3(hqP,isAck,fdbk)
3231 RgSchDlHqProcCb *hqP;
3236 U8 cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
3237 isAck[0] = (U8)fdbk[cellIdx];
3238 isAck[1] = (U8)fdbk[cellIdx + 1];
3241 /** * @brief Handler for HARQ feedback received for DL transmission.
3245 * Function : rgSCHDhm5gtfHqFdbkInd
3247 * This function shall act on the feedback received from TOM for DL
3248 * transmission. If the feedback for msg4 is final (after max transmissions
3249 * or ACK) inform RAM that Msg4 transmission is done.
3252 * @param[in] Void *cb
3253 * @param[in] U8 cbType
3254 * @param[in] RgSchCellCb *cell
3255 * @param[in] RgTfuHarqAckIndInfo *fdbk
3256 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3257 * @param[in] RgSchErrInfo *err
3263 PUBLIC S16 rgSCHDhm5gtfHqFdbkInd
3267 CmLteTimingInfo timingInfo,
3272 PUBLIC S16 rgSCHDhm5gtfHqFdbkInd(ue, cell, timingInfo, fdbk, err)
3275 CmLteTimingInfo timingInfo;
3280 RgSchDlHqProcCb *hqP = NULLP;
3281 CmLList *node = NULLP;
3285 Bool isMsg4 = FALSE;
3289 RgInfRlsHqInfo *rlsHqBufs = NULLP;
3291 TRC2(rgSCHDhm5gtfHqFdbkInd)
3293 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3295 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3297 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3299 hqPCount = lnk->count;
3304 hqP = (RgSchDlHqProcCb *)node->node;
3306 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3307 procId = hqP->procId;
3309 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3311 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
3313 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
3314 timingInfo, fdbk, rlsHqBufs, err);
3316 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3318 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3319 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3321 rlsHqBufs->numUes++;
3327 } /* rgSCHDhm5gtfHqFdbkInd */
3329 /** * @brief Handler for HARQ feedback received for DL transmission.
3333 * Function : rgSCHDhmHqFdbkInd
3335 * This function shall act on the feedback received from TOM for DL
3336 * transmission. If the feedback for msg4 is final (after max transmissions
3337 * or ACK) inform RAM that Msg4 transmission is done.
3340 * @param[in] Void *cb
3341 * @param[in] U8 cbType
3342 * @param[in] RgSchCellCb *cell
3343 * @param[in] RgTfuHarqAckIndInfo *fdbk
3344 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3345 * @param[in] RgSchErrInfo *err
3351 PUBLIC S16 rgSCHDhmHqFdbkInd
3356 CmLteTimingInfo timingInfo,
3358 RgInfRlsHqInfo *rlsHqBufs,
3362 PUBLIC S16 rgSCHDhmHqFdbkInd(cb, cbType, cell, timingInfo, fdbk, rlsHqBufs, err)
3366 CmLteTimingInfo timingInfo;
3368 RgInfRlsHqInfo *rlsHqBufs;
3372 RgSchDlHqTbCb *tbCb;
3373 RgSchDlHqEnt *hqE = NULLP;
3374 RgSchDlHqProcCb *hqP = NULLP;
3375 CmLList *node = NULLP;
3377 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3378 RgSchUeCb *ue = NULLP;
3382 Bool isMsg4 = FALSE;
3383 RgSchRaCb *raCb = NULLP;
3385 /* Added Insure Fixes Of UR.Initialized procId */
3387 /* DTX Change: Bool is converted into U8*/
3388 U8 isAck[2]={0}; /*Changed to Array of 2*/
3393 CmLteTimingInfo fdbkRcptTime = timingInfo;
3394 #ifdef RGSCH_SPS_STATS
3395 RgSchCmnDlHqProc *cmnHqDl;
3399 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3401 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3403 TRC2(rgSCHDhmHqFdbkInd)
3405 /* Get the subframe associated with the feedback */
3406 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3407 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3408 * serving the purpose */
3409 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3411 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3412 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3414 raCb = (RgSchRaCb *)(cb);
3416 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3422 rnti = raCb->tmpCrnti;
3426 ue = (RgSchUeCb *)(cb);
3427 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3429 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3432 hqPCount = lnk->count;
3435 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3440 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3441 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3442 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3443 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3444 from get CQI from cmInfo->cqi
3445 from cmInfo get iTbs cmInfo->iTbs[0]
3446 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3447 Update stats in cellCb
3448 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3449 if (fdbk->isAck == TRUE)
3450 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3452 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3453 DL Ack/Nack statistics
3455 #ifdef MAC_SCH_STATS
3456 if (hqE->ue != NULLP)
3458 RgSchUeCb *ueCb = hqE->ue;
3459 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3460 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3461 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3462 static U32 retxCnt = 0;
3464 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3466 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3471 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3473 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3474 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3476 #endif /* MAC_SCH_STATS */
3478 /* Fetch the harqProc from the inUse list */
3480 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3481 /* Call Common module with the feedback information */
3482 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3484 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3486 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3489 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3490 {/* Feedback for SPS Release on PCell
3491 If Pcell is in mimo, feedback index will be 0
3493 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3495 isAck[0] = fdbk->isAck[0];
3498 isAck[0] = fdbk->isAck[2];
3501 /* Not releasing pdcch here
3502 * as it is already done at the time of
3504 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3511 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
3512 "CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3513 "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3518 isAck[0] = fdbk->isAck[0];
3519 /* Note: Since relPdcchFbkTimimg matches with the recieved
3520 * feedback, assumed that feedback is for release PDCCH */
3521 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3523 /* Remove release PDCCH from the subframe */
3524 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3525 sf->relPdcch = NULLP;
3530 #endif /* LTEMAC_SPS */
3532 /* Remove the harq process from the subframe */
3533 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3534 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3547 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3549 hqP = (RgSchDlHqProcCb *)node->node;
3551 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3553 procId = hqP->procId;
3555 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3557 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3558 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3560 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3562 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3567 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3569 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3571 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3573 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3574 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3577 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3579 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3580 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3582 rlsHqBufs->numUes++;
3587 node = sf->ackNakRepQ.first;
3590 tbCb = (RgSchDlHqTbCb *)(node->node);
3593 procId = hqP->procId;
3594 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3595 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3596 if (HQ_TB_WAITING == tbCb->state)
3598 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3599 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3600 timingInfo, isAck[0], rlsHqBufs, err);
3602 hqP->cwSwpEnabled = FALSE;
3603 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3605 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3606 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3608 rlsHqBufs->numUes++;
3615 } /* rgSCHDhmHqFdbkInd */
3616 #endif /* LTE_FDD */
3620 * @brief Handler for Harq related UE configuration.
3624 * Function : rgSCHDhmRgrUeCfg
3626 * This function shall fetch the harq related information into the
3627 * respective ueCb from the UE configuration as provided by the
3630 * @param[in] RgSchCellCb *cell
3631 * @param[in] RgSchUeCb *ueCb
3632 * @param[in] RgrUeCfg *ueCfg
3633 * @param[out] RgSchErrInfo *err
3639 PUBLIC Void rgSCHDhmRgrUeCfg
3647 PUBLIC Void rgSCHDhmRgrUeCfg(cell, ueCb, ueCfg, err)
3654 TRC2(rgSCHDhmRgrUeCfg)
3658 /* Initialize the TA Timer */
3659 cmInitTimers(&ueCb->taTmr, 1);
3661 /* Setting these values irrespective of taTmr value */
3662 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3663 /* Corrected default value of TA as per 36.213, 4.2.3 */
3664 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3666 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3667 ueCb->dl.taCb.outStndngTa = FALSE;
3668 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3670 /* Start TA timer only if cfgd as FINITE value */
3671 if (ueCfg->ueTaTmrCfg.pres)
3673 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3674 * TA command before the expiry of TA at UE. Also considering for
3675 * possible retx for this TA command */
3676 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3677 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3679 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3681 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3684 } /* rgSCHDhmRgrUeCfg */
3688 * @brief Handler for HARQ related UE Reconfiguration
3692 * Function : rgSCHDhmRgrCellCfg
3694 * This function shall fetch the HARQ related information into the
3695 * respective ueCb from the UE configuration as provided by the
3698 * @param[in] RgSchCellCb *cell
3699 * @param[in] RgrCellCfg *cellCfg
3700 * @param[out] RgSchErrInfo *err
3707 PUBLIC Void rgSCHDhmRgrCellCfg
3710 RgrCellCfg *cellCfg,
3714 PUBLIC Void rgSCHDhmRgrCellCfg(cell, cellCfg, err)
3716 RgrCellCfg *cellCfg;
3721 PTR pUeCb;/* previous UE Control block */
3722 PTR nUeCb;/* next UE control block */
3726 TRC2(rgSCHDhmRgrCellCfg)
3732 cell->dlHqCfg = cellCfg->dlHqCfg;
3735 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3743 /* Update the DL Harq related information */
3744 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3745 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3748 /* Initializing the list for ueCbs that would have ta */
3749 cmLListInit(&cell->taUeLst);
3751 cmLListInit(&cell->ccchSduUeLst);
3752 cmLListInit(&cell->contResGrdTmrLst);
3753 cmLListInit(&cell->contResTmrLst);
3755 if(cell->emtcEnable)
3757 rgSCHDhmEmtcRgrCellCfg(cell);
3762 /* Initializing the timer queue */
3763 cell->tqCp.nxtEnt = 0;
3764 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3766 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3768 cell->tq[idx].first = NULLP;
3769 cell->tq[idx].tail = NULLP;
3772 } /* rgSCHDhmRgrCellCfg */
3775 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3779 * Function : rgSCHDhmRgrCellRecfg
3781 * This function shall fetch the HARQ related information into the
3782 * respective ueCb from the UE configuration as provided by the
3785 * @param[in] RgSchCellCb *cell
3786 * @param[in] RgrCellRecfg *cellRecfg
3787 * @param[out] RgSchErrInfo *err
3794 PUBLIC Void rgSCHDhmRgrCellRecfg
3797 RgrCellRecfg *cellRecfg,
3801 PUBLIC Void rgSCHDhmRgrCellRecfg(cell, cellRecfg, err)
3803 RgrCellRecfg *cellRecfg;
3808 PTR pUeCb;/* previous UE Control block */
3809 PTR nUeCb;/* next UE control block */
3812 TRC2(rgSCHDhmRgrCellRecfg)
3818 /* Update the cell with recieved configuration */
3819 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3821 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3825 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3833 /* Update the DL Harq related information */
3834 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3835 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3840 } /* rgSCHDhmRgrCellRecfg */
3843 * @brief Handler for freeing up the HARQ related information from ueCb
3847 * Function : rgSCHDhmFreeUe
3849 * This function shall free up the HARQ specific information from ueCb.
3851 * @param[in] RgSchUeCb *ueCb
3857 PUBLIC Void rgSCHDhmFreeUe
3862 PUBLIC Void rgSCHDhmFreeUe(ueCb)
3867 TRC2(rgSCHDhmFreeUe)
3869 /* If TA Timer is running. Stop it */
3870 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3872 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3875 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3876 * doesn't expire after UE is deleted */
3878 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3880 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3882 #endif /* ifdef RGR_V1*/
3885 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3887 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3890 /* This UE needs to be removed from its entry into cell's taUeLst */
3891 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3892 if(ueCb->taLnk.node)
3894 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3895 ueCb->taLnk.node = NULLP;
3898 if (ueCb->dlTaLnk.node != NULLP)
3900 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3901 * function directly from other modules. APIs should be defined and/or used
3902 * instead. Please check for other possible incorrect usage. */
3903 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3908 } /* rgSCHDhmFreeUe */
3911 * @brief Handler for updating the TA.
3915 * Function : rgSCHDhmUpdTa
3917 * This function shall update the TA received.
3919 * @param[in] RgSchCellCb *cell
3920 * @param[in] RgSchUeCb *ueCb
3927 PUBLIC Void rgSCHDhmUpdTa
3934 PUBLIC Void rgSCHDhmUpdTa(cell, ueCb, ta)
3942 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3944 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3945 ueCb->dl.taCb.numRemSf = 2;
3946 rgSCHUtlDlTARpt(cell, ueCb);
3947 /* If TA Timer is running. Stop it */
3948 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3950 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3953 /* SR_RACH_STATS : TA MODIFIED */
3954 if (ueCb->dl.taCb.ta != ta)
3958 ueCb->dl.taCb.ta = ta;
3962 /* [ccpu00121813]-ADD-Updating outstanding values
3963 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3964 * has been scheduled,further TA values get stored in outstndngTaval.
3965 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3966 * then schedule the outstanding TA val if present */
3967 ueCb->dl.taCb.outStndngTa = TRUE;
3968 ueCb->dl.taCb.outStndngTaval = ta;
3972 } /* rgSCHDhmUpdTa */
3974 /** @brief This function handles the TA timer expiry.
3978 * Function: This function handled the TA Expiry.
3984 * @param[in] RgSchUeCb *ueCb
3990 PUBLIC Void rgSCHDhmProcTAExp
3995 PUBLIC Void rgSCHDhmProcTAExp (ueCb)
3999 TRC2(rgSCHDhmProcTAExp);
4001 /* Ask scheduler to schedule this UE */
4002 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
4003 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
4005 } /* end of rgSCHDhmProcTAExp */
4007 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
4009 * @brief Handler for Adding scheduled logical channel data information
4014 * Function : rgSCHDhmAddLcData
4016 * This function shall add the scheduled logical channel data
4017 * information to the HARQ process.
4019 * @param[in] RgSchLchAllocInfo *lchData
4020 * @param[in] RgSchDlHqTbCb *tbInfo
4026 PUBLIC S16 rgSCHDhmAddLcData
4029 RgSchLchAllocInfo *lchData,
4030 RgSchDlHqTbCb *tbInfo
4033 PUBLIC S16 rgSCHDhmAddLcData(inst, lchData, tbInfo)
4035 RgSchLchAllocInfo *lchData;
4036 RgSchDlHqTbCb *tbInfo;
4040 TRC2(rgSCHDhmAddLcData)
4042 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
4047 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
4053 } /* rgSCHDhmAddLcData */
4057 * @brief Handler for releaseing the subframe allocation.
4061 * Function : rgSCHDhmTddRlsSubFrm
4063 * This function shall be invoked to release the DL Sf
4064 * allocations for which HARQ feedback time has expired.
4066 * @param[in] RgSchCellCb *cellCb
4067 * @param[in] CmLteTimingInfo uciTimingInfo;
4073 PUBLIC S16 rgSCHDhmTddRlsSubFrm
4075 RgSchCellCb *cellCb,
4076 CmLteTimingInfo uciTimingInfo
4079 PUBLIC S16 rgSCHDhmTddRlsSubFrm(cellCb, uciTimingInfo)
4080 RgSchCellCb *cellCb;
4081 CmLteTimingInfo uciTimingInfo;
4084 CmLteTimingInfo dlSfTime;
4085 RgSchTddDlAscSetIdxK ascIdx;
4089 TRC2(rgSCHDhmTddRlsSubFrm)
4092 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4093 noFdbks = ascIdx.numFdbkSubfrms;
4094 for(i=0; i < noFdbks; i++)
4096 /* Get the subframe and sfn for which HARQ Ack/Nack
4098 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4099 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4100 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4101 * as it is serving the purpose */
4102 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4103 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
4106 }/* rgSCHDhmTddRlsSubFrm */
4112 * @brief Handler for Removing the HARQ process from a dlsf.
4116 * Function : rgSCHDhmRlsDlsfHqProc
4118 * This function shall be invoked for every tti. It goes back to
4119 * to the sixth last subframe to check whether it still exists. If
4120 * that exists this function traverses through the entire harq
4121 * proc list associated and frees up all of them.
4123 * @param[in] RgSchCellCb *cellCb
4124 * @param[in] CmLteTimingInfo timingInfo
4130 PUBLIC S16 rgSCHDhmRlsDlsfHqProc
4132 RgSchCellCb *cellCb,
4133 CmLteTimingInfo uciTimingInfo
4136 PUBLIC S16 rgSCHDhmRlsDlsfHqProc(cellCb, uciTimingInfo)
4137 RgSchCellCb *cellCb;
4138 CmLteTimingInfo uciTimingInfo;
4142 CmLteTimingInfo dlSfTime;
4143 CmLteTimingInfo nxtfrm = {0,0};
4144 RgSchDlHqProcCb *tmpHqProc;
4145 RgSchTddDlAscSetIdxK ascIdx;
4148 RgSchDlSf *nxtDlsf = NULLP;
4152 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
4154 RgSchTddANInfo *anInfo = NULLP;
4155 RgSchDlHqTbCb *tbCb;
4156 RgSchUeCb *ue = NULLP;
4157 TRC2(rgSCHDhmRlsDlsfHqProc)
4160 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
4161 noFdbks = ascIdx.numFdbkSubfrms;
4162 for(i=0; i < noFdbks; i++)
4164 /* Get the subframe and sfn for which HARQ Ack/Nack
4166 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4167 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4168 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4169 * as it is serving the purpose */
4170 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4172 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
4173 if(cellCb->ulDlCfgIdx != 5)
4175 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
4177 /* Subframe is present. Delete all the harq associations from
4181 /*Handling for Msg4*/
4182 node = dlSf->msg4HqPLst.first;
4185 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4187 tmpHqProc->cwSwpEnabled = FALSE;
4188 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4190 tbCb = &tmpHqProc->tbInfo[0];
4192 /* Fix : syed MultiUe per TTI crash in TA List. */
4196 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4199 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4201 /* Delete the Harq Association. Release the Harq Process */
4202 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4204 if (tbCb->taSnt == TRUE)
4206 /* [ccpu00127148] Correcting the check */
4207 if (TRUE == maxRetx)
4209 tbCb->taSnt = FALSE;
4210 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4211 ue->dl.taCb.state = RGSCH_TA_IDLE;
4213 rgSCHUtlReTxTa(cellCb, ue);
4219 node = dlSf->ueLst.first;
4225 ue = (RgSchUeCb *)(node->node);
4229 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
4232 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4233 hqPNode = hqPNode->next;
4234 for (idx = 0 ;idx < 2; idx++)
4236 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4238 tbCb = &tmpHqProc->tbInfo[idx];
4240 /* Fix : syed MultiUe per TTI crash in TA List. */
4244 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4247 /* Update feedback time for this process so that
4248 * next subframe its picked up */
4250 U8 servCellIdx = rgSchUtlGetServCellIdx(
4251 tmpHqProc->hqE->cell->instIdx,
4252 tmpHqProc->hqE->cell->cellId,
4254 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4256 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
4260 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
4261 "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX"
4262 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
4263 uciTimingInfo.slot));
4265 else if (tbCb->fbkRepCntr == 0)
4267 /* Initialise the Ack/Nack feedback */
4269 if(!(anInfo->dlDai))
4271 rgSCHUtlInitUeANFdbkInfo(anInfo);
4276 /* Update feedback time for this process so that
4277 * * next subframe its picked up */
4278 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4279 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4280 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4281 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
4286 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4287 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
4290 /* Delete the Harq Association. Release the Harq Process */
4291 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4293 if (tbCb->taSnt == TRUE)
4295 /* [ccpu00127148] Correcting the check */
4296 if (TRUE == maxRetx)
4298 tbCb->taSnt = FALSE;
4299 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4300 ue->dl.taCb.state = RGSCH_TA_IDLE;
4302 rgSCHUtlReTxTa(cellCb, ue);
4304 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4305 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4314 node = dlSf->ackNakRepQ.first;
4317 tbCb = (RgSchDlHqTbCb *)(node->node);
4318 tmpHqProc = tbCb->hqP;
4319 /* [ccpu00121813]-ADD-Fetch ueCb */
4320 ue = tmpHqProc->hqE->ue;
4321 /* Fix : syed MultiUe per TTI crash in TA List. */
4326 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
4327 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
4331 /* If This is not the last repetition */
4332 if (tbCb->fbkRepCntr > 1)
4334 /* Update feedback time for this process so that
4335 * next subframe its picked up */
4337 U8 servCellIdx = rgSchUtlGetServCellIdx(
4338 tmpHqProc->hqE->cell->instIdx,
4339 tmpHqProc->hqE->cell->cellId,
4341 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4343 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
4349 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4350 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4351 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4352 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4358 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4360 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
4362 /*even if one NACK, we consider the feedback
4363 * on a whole as NACk */
4364 if ( tbCb->nackCount != 0 )
4366 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4370 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4374 /* Delete the Harq Association. Release the Harq Process */
4375 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4377 }/*if(((tbCb->nackCount+....*/
4380 if (tbCb->taSnt == TRUE)
4382 /* [ccpu00127148] Correcting the check */
4383 if (TRUE == maxRetx)
4385 tbCb->taSnt = FALSE;
4386 ue->dl.taCb.state = RGSCH_TA_IDLE;
4388 rgSCHUtlReTxTa(cellCb, ue);
4389 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4390 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4397 }/* rgSCHDhmRlsDlsfHqProc */
4398 #else /* ifdef LTE_TDD */
4400 * @brief Handler for Removing the HARQ process from a dlsf.
4404 * Function : rgSCHDhmRlsDlsfHqProc
4406 * This function shall be invoked for every tti. It goes back to
4407 * to the sixth last subframe to check whether it still exists. If
4408 * that exists this function traverses through the entire harq
4409 * proc list associated and frees up all of them.
4411 * @param[in] RgSchCellCb *cell
4417 PUBLIC S16 rgSCHDhmRlsDlsfHqProc
4420 CmLteTimingInfo timingInfo
4423 PUBLIC S16 rgSCHDhmRlsDlsfHqProc(cell, timingInfo)
4425 CmLteTimingInfo timingInfo;
4429 CmLteTimingInfo frm;
4430 RgSchDlHqProcCb *tmpHqProc;
4435 RgSchDlHqTbCb *tbCb;
4438 TRC2(rgSCHDhmRlsDlsfHqProc)
4440 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
4441 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4442 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4443 * as it is serving the purpose */
4444 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
4447 /* Get the required Last subframe */
4448 sf = rgSCHUtlSubFrmGet(cell, frm);
4451 /*Handling for Msg4*/
4452 node = sf->msg4HqPLst.first;
4455 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4456 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4458 tbCb = &tmpHqProc->tbInfo[0];
4459 /* Fix : syed MultiUe per TTI crash in TA List. */
4462 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4463 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4466 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4467 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4469 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4474 if (tbCb->fbkRepCntr != 0)
4476 /* Update timingInfo for this hqP so that next subframe its picked up */
4477 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4478 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4482 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4484 /* Delete the Harq Association. Release the Harq Process */
4485 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4489 /* Subframe is present. Delete all the harq associations from
4492 node = sf->ueLst.first;
4495 ue = (RgSchUeCb *)(node->node);
4499 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4503 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4504 tmpHqProc->cwSwpEnabled = FALSE;
4505 hqPNode = hqPNode->next;
4506 for (idx = 0 ;idx < 2; idx++)
4508 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4510 tbCb = &tmpHqProc->tbInfo[idx];
4511 /* Fix : syed MultiUe per TTI crash in TA List. */
4514 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4515 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4518 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4519 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4521 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4526 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4529 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4532 /* Delete the Harq Association. Release the Harq Process */
4533 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4535 if (tbCb->taSnt == TRUE)
4537 /* [ccpu00127148] Correcting the check */
4538 if (TRUE == maxRetx)
4540 tbCb->taSnt = FALSE;
4541 ue->dl.taCb.state = RGSCH_TA_IDLE;
4543 rgSCHUtlReTxTa(cell, ue);
4544 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4545 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4548 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4549 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4558 } /* rgSCHDhmRlsDlsfHqProc */
4563 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4568 * Function: rgSCHDhmMarkSpsHqProc
4569 * Purpose: This function returns the HARQ process with the given ID.
4570 * Invoked by: SPS Module
4572 * - Get the HARQ process by index from the UE
4573 * - Set isSpsHqProc = TRUE
4575 * @param[in] RgSchUeCb *ue
4578 * -# ROK if successful
4579 * -# RFAILED otherwise
4583 PUBLIC S16 rgSCHDhmMarkSpsHqProc
4589 PUBLIC S16 rgSCHDhmMarkSpsHqProc(ue, idx)
4594 RgSchDlHqProcCb *hqP;
4595 TRC2(rgSCHDhmMarkSpsHqProc)
4597 /* Pick the proc based on the index provided */
4598 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4601 } /* rgSCHDhmMarkSpsHqProc */
4602 #endif /* RG_UNUSED */
4603 #endif /* LTEMAC_SPS */
4606 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4610 * Function : rgSCHDhmProcHqFdbkAckNackRep
4612 * This function shall act on the feedback received from TOM for DL
4616 * @param[in] RgSchDlHqProcCb *hqP
4617 * @param[in] RgSchDlSf *sf
4618 * @param[in] U8 tbCnt
4619 * @param[in] U8 *isAck
4625 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep
4627 RgSchDlHqProcCb *hqP,
4633 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,isAck)
4634 RgSchDlHqProcCb *hqP;
4640 TRC2(rgSCHDhmProcHqFdbkAckNackRep)
4641 /* Check if this is repeating UE */
4642 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4643 /* Check if last repetition */
4644 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4646 /* Update timingInfo for this hqP so that next subframe its picked up */
4647 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4648 hqP->tbInfo[tbCnt].timingInfo, 1);
4652 /* Take decision here based on the number
4653 * of DTX's,NACK's and ACK's received
4655 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4656 (hqP->tbInfo[tbCnt].dtxCount)))
4658 *isAck = TFU_HQFDB_ACK;
4660 /*even a single NACK indicates that UE received
4663 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4665 *isAck = TFU_HQFDB_NACK;
4669 *isAck = TFU_HQFDB_DTX;
4673 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4676 #endif /* ifndef LTE_TDD */
4679 /* Freeing up the HARQ proc blocked for
4680 * indefinite time in case of Retx */
4682 * @brief This function handles the scenario in case Retx allocation is failed.
4686 * Function: rgSCHDhmDlRetxAllocFail
4689 * @param[in] RgSchUeCb *ue
4690 * @param[in] RgSchDlHqProcCb *hqP
4695 PUBLIC S16 rgSCHDhmDlRetxAllocFail
4698 RgSchDlHqProcCb *hqP
4701 PUBLIC S16 rgSCHDhmDlRetxAllocFail(ue, hqP)
4703 RgSchDlHqProcCb *hqP;
4707 RgInfRlsHqInfo *rlsHqInfo;
4709 Bool maxRetx = FALSE;
4710 RgSchCmnCell *cellSch;
4712 TRC2(rgSCHDhmDlRetxAllocFail);
4714 cell = hqP->hqE->cell;
4715 cellSch = RG_SCH_CMN_GET_CELL(cell);
4716 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4718 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4719 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4721 hqP->tbInfo[0].cntrRetxAllocFail++;
4724 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4725 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4727 hqP->tbInfo[1].cntrRetxAllocFail++;
4730 /* initialize MAC-SCH interface HARQ release info */
4731 rlsHqInfo->numUes = 0;
4732 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4734 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4735 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4737 if (hqP->hqE->msg4Proc == hqP)
4739 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4743 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4746 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4751 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4752 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4756 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4757 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4760 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4761 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4764 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4765 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4766 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4769 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4770 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4772 if (hqP->hqE->msg4Proc == hqP)
4774 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4778 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4781 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4783 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4784 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4785 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4786 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4787 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4790 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4792 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4793 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4795 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4798 /* send HARQ release to MAC */
4799 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4801 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4802 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4803 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4804 rlsHqInfo->numUes = 1;
4806 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4807 RgSchMacRlsHq(&pst, rlsHqInfo);
4815 PRIVATE S16 rgSCHDhmUpdateAckNackHistory
4823 PRIVATE S16 rgSCHDhmUpdateAckNackHistory(cell, ueCb, hqfdbk, tbCnt)
4834 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4837 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4840 if (hqfdbk == TFU_HQFDB_ACK)
4842 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4846 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4849 printf("deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4850 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4851 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4854 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4860 PUBLIC S16 rgSCHDhmUpdBlerBasediTbsEff
4867 PUBLIC S16 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt)
4877 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4878 U8 cfi = cellSch->dl.currCfi;
4879 U8 maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4880 maxiTbs = RG_SCH_DL_MAX_ITBS;
4882 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4883 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4887 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4888 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4892 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4893 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4897 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4898 ueDl->laCb[tbCnt].deltaiTbs)/100),
4899 ueCb->cell->thresholds.maxDlItbs);
4902 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4904 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4906 /* Eff for CW for 1 Layer Tx */
4907 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4908 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4909 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4911 /* Eff for CW for 2 Layer Tx */
4912 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4913 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4914 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4922 * @brief This function Processes the Hq Fdbk in case of
4923 * special Bundling in TDD (FAPIv1.1: Table 79)
4927 * Function: rgSCHDhmPrcSplBundlFdbk
4928 * Purpose: To Interpret the Harq Feedback according to
4929 * table 7.3-1: 36.213
4931 * 0 = 0 or None (UE detect at least one DL is missed)
4932 * 1 = 1 or 4 or 7 ACKs reported
4933 * 2 = 2 or 5 or 8 ACKs reported
4934 * 3 = 3 or 6 or 9 ACKs reported
4935 * 4 = DTX (UE did not transmit anything)
4937 * @param[in] TfuHqInfo *fdbk
4938 * @param[in] U8 hqCnt
4943 PRIVATE Void rgSCHDhmPrcSplBundlFdbk
4950 PRIVATE Void rgSCHDhmPrcSplBundlFdbk(cell, fdbk, hqCnt)
4960 TRC2(rgSCHDhmPrcSplBundlFdbk);
4962 /* Num of ACKs reported by UE */
4963 numOfAcks = fdbk->isAck[0];
4965 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4966 fdbk->isAck[0] == TFU_HQFDB_DTX)
4972 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4973 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4975 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4978 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4979 the PDSCH trasnmission (spatial bundling). So we have
4980 to assume same feedback for both codewords */
4982 for(U8 idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4984 fdbk->isAck[idx] = fdbk->isAck[0];
4987 fdbk->isAck[1] = fdbk->isAck[0];
4995 * @brief This function adds HARQ process to FREE list
4999 * Function: rgSCHDhmHqPAdd2FreeLst
5002 * Invoked by: scheduler
5004 * @param[out] RgDlHqProc *hqP
5009 PUBLIC Void rgSCHDhmHqPAdd2FreeLst
5011 RgSchDlHqProcCb *hqP
5014 PUBLIC Void rgSCHDhmHqPAdd2FreeLst(hqP)
5015 RgSchDlHqProcCb *hqP;
5018 TRC2(rgSCHDhmHqPAdd2FreeLst)
5024 printf("Crashing already part of free lst\n");
5025 printf("Crashing %d \n", *p);
5029 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
5030 hqP->hqPLst = &hqP->hqE->free;
5034 if (hqP->hqE->free.count > 8)
5037 printf("Crashing invalid hq count\n");
5038 printf("Crashing %d \n", *p);
5044 rgSCHLaaHndlHqProcFree(hqP);
5048 } /* rgSCHDhmHqPAdd2FreeLst */
5052 * @brief This function adds HARQ process to inUse list
5056 * Function: rgSCHDhmHqPAdd2InUseLst
5059 * Invoked by: scheduler
5061 * @param[out] RgDlHqProc *hqP
5066 PUBLIC Void rgSCHDhmHqPAdd2InUseLst
5068 RgSchDlHqProcCb *hqP
5071 PUBLIC Void rgSCHDhmHqPAdd2InUseLst(hqP)
5072 RgSchDlHqProcCb *hqP;
5075 TRC2(rgSCHDhmHqPAdd2InUseLst)
5081 printf("Crashing already part of inuse lst\n");
5082 printf("Crashing %d \n", *p);
5086 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
5087 hqP->hqPLst = &hqP->hqE->inUse;
5091 if (hqP->hqE->inUse.count > 8)
5094 printf("Crashing invalid hq count \n");
5095 printf("Crashing %d \n", *p);
5101 } /* rgSCHDhmHqPAdd2InUseLst */
5104 * @brief This function adds HARQ process to FREE list
5108 * Function: rgSCHDhmHqPDelFrmFreeLst
5111 * Invoked by: scheduler
5113 * @param[out] RgDlHqProc *hqP
5118 PUBLIC Void rgSCHDhmHqPDelFrmFreeLst
5120 RgSchDlHqProcCb *hqP
5123 PUBLIC Void rgSCHDhmHqPDelFrmFreeLst(hqP)
5124 RgSchDlHqProcCb *hqP;
5127 TRC2(rgSCHDhmHqPDelFrmFreeLst)
5133 printf("Crashing not part of any lst\n");
5134 printf("Crashing %d \n", *p);
5139 if (hqP->hqPLst != &hqP->hqE->free)
5142 printf("Crashing del from wrong lst\n");
5143 printf("Crashing %d \n", *p);
5148 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
5149 hqP->hqPLst = NULLP;
5152 if (hqP->hqE->free.count > 8)
5155 printf("Crashing invalid hq count\n");
5156 printf("Crashing %d \n", *p);
5162 } /* rgSCHDhmHqPDelFrmFreeLst */
5167 * @brief This function adds HARQ process to FREE list
5171 * Function: rgSCHDhmHqPDelFrmInUseLst
5174 * Invoked by: scheduler
5176 * @param[out] RgDlHqProc *hqP
5181 PUBLIC Void rgSCHDhmHqPDelFrmInUseLst
5183 RgSchDlHqProcCb *hqP
5186 PUBLIC Void rgSCHDhmHqPDelFrmInUseLst(hqP)
5187 RgSchDlHqProcCb *hqP;
5190 TRC2(rgSCHDhmHqPDelFrmInUseLst)
5196 printf("Crashing not part of any lst\n");
5197 printf("Crashing %d \n", *p);
5203 if (hqP->hqPLst != &hqP->hqE->inUse)
5206 printf("Crashing del from wrong lst\n");
5207 printf("Crashing %d \n", *p);
5212 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
5213 hqP->hqPLst = NULLP;
5216 if (hqP->hqE->inUse.count > 8)
5219 printf("Crashing invalid hq count\n");
5220 printf("Crashing %d \n", *p);
5226 } /* rgSCHDhmHqPDelFrmInUseLst */
5229 /**********************************************************************
5232 **********************************************************************/