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.
36 /* header include files -- defines (.h) */
37 #include "common_def.h"
43 #include "rg_sch_err.h"
44 #include "rg_sch_inf.h" /* typedefs for Scheduler */
46 #include "rg_sch_cmn.h"
48 /* header/extern include files (.x) */
53 #include "rg_sch_inf.x" /* typedefs for Scheduler */
55 #include "rg_sch_cmn.x"
57 #ifdef RGSCH_SPS_STATS
58 uint32_t rgNumSPSSchedDropMaxRetx;
66 RgSchNackAckStats hqFailStats;
67 RgSchHqRetxStats hqRetxStats;
68 #endif /* MAC_SCH_STATS */
69 //Chandan Stats Collection
72 RgSchDlHqStats dlHqStats[10000] = {{0,0,0}};
76 /* For special bundling case: convert numOfAcks to ACK/NACK
77 * The below table derives the HARQ aknowledgement as ACK or NACK using the
78 * number of transmission done and the feedback value received
79 * The below table is based on Table 7.3-X from 36.213 and
80 * table 79 from FAPIv1.1 doc
82 uint8_t rgSchNumOfAcksToAckNack[RG_SCH_MAX_NUM_EXPECTED_ACKS][RG_SCH_NUM_FDBK_VALUE] = {
83 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
84 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
85 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
86 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
87 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
88 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
89 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
90 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
91 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK}
99 static Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, uint8_t tbIdx, uint8_t fdbk,
100 Bool maxHqRetxReached));
101 void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
103 static S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
104 RgSchDlHqProcCb *hqP,
111 static S16 rgSCHDhmUpdateAckNackHistory ARGS((
119 static Void rgSCHDhmPrcSplBundlFdbk ARGS((
125 static Void rgSchGetHqFdbkPosForM1 ARGS((
127 RgSchDlHqProcCb *hqP,
131 RgSchTddANInfo *anInfo
133 static Void rgSchGetHqFdbkPosForM234 ARGS((
135 RgSchDlHqProcCb *hqP,
139 RgSchTddANInfo *anInfo,
141 CmLteTimingInfo timeInfo
146 /* Freeing up the HARQ proc blocked for
147 * indefinite time in case of Retx */
148 S16 rgSCHDhmDlRetxAllocFail ARGS((
150 RgSchDlHqProcCb *proc
154 S16 rgSCHDhmEmtcRgrCellCfg ARGS((
160 uint32_t gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
161 uint32_t gSCellSchedCount,gPrimarySchedCount;
162 uint32_t gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
163 uint32_t gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
164 uint32_t gHqFdbkCount;
168 Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
170 RgSchEmtcDlSf *subFrm,
171 RgSchDlHqProcCb *hqP,
175 RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
180 Void rgSCHEmtcHqInfoAlloc ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP));
182 /* forward references */
185 * @brief This function initializes the DL HARQ Entity of UE.
189 * Function: rgSCHDhmHqEntInit
190 * Purpose: This function initializes the DL HARQ entity of
191 * UE control block. This is performed at the time
192 * of creating UE control block.
194 * Invoked by: configuration module
196 * @param[in] RgSchCellCb* cell
197 * @return RgSchDlHqEnt *
200 /*MS_WORKAROUND for ccpu00122893*/
201 Void rgSCHDhmHqEntReset(RgSchDlHqEnt *hqE)
203 RgSchDlHqProcCb *hqP;
205 cmLListInit(&hqE->inUse);
206 cmLListInit(&hqE->free);
207 for (i=0; i < hqE->numHqPrcs; i++)
209 hqP = &hqE->procs[i];
212 /* Fix - reset numLch */
213 hqP->tbInfo[0].numLch = 0;
214 hqP->tbInfo[1].numLch = 0;
215 hqP->tbInfo[0].txCntr = 0;
216 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
217 hqP->tbInfo[1].txCntr = 0;
218 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
219 hqP->tbInfo[0].tbIdx = 0;
220 hqP->tbInfo[1].tbIdx = 1;
221 hqP->tbInfo[0].hqP = hqP;
222 hqP->tbInfo[1].hqP = hqP;
223 hqP->tbInfo[0].state = HQ_TB_ACKED;
224 hqP->tbInfo[1].state = HQ_TB_ACKED;
225 hqP->tbInfo[0].contResCe = NOTPRSNT;
226 hqP->tbInfo[1].contResCe = NOTPRSNT;
227 hqP->lnk.node = (PTR)hqP;
228 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
230 rgSCHDhmHqPAdd2FreeLst(hqP);
231 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
232 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
233 hqP->drxCb.rttIndx = DRX_INVALID;
234 hqP->drxCb.reTxIndx = DRX_INVALID;
235 hqP->tbInfo[0].cntrRetxAllocFail = 0;
236 hqP->tbInfo[1].cntrRetxAllocFail = 0;
237 hqP->hasDcch = FALSE;
238 hqP->cwSwpEnabled = FALSE;
243 rgSCHLaaResetDlHqProcCb(hqP);
247 } /* rgSCHDhmHqEntReset */
250 * @brief This function assigns dlHqEnt of raCb to ueCb.
254 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
255 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
257 * Invoked by: configuration module
259 * @param[in] RgSchUeCb *ue
260 * @param[in] RgSchRaCb *raCb
264 Void rgSCHDhmAssgnUeHqEntFrmRaCb(RgSchUeCb *ue,RgSchRaCb *raCb)
267 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
268 ue->cellInfo[0]->hqEnt->ue = ue;
269 /* Update the DL Harq related information */
270 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
272 /* Fix : set UE active in DL as UE initialization completed */
273 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
274 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
275 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
281 * @brief This function deletes the dlHqEnt.
285 * Function: rgSCHDhmDelHqEnt
286 * Purpose: This function deletes the dlHqEnt.
288 * Invoked by: configuration module
290 * @param[in] RgSchCellCb *cell
291 * @param[in] RgSchDlHqEnt **hqE
295 Void rgSCHDhmDelHqEnt(RgSchCellCb *cell,RgSchDlHqEnt **hqE)
303 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
305 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
306 sizeof(RgSchDlHqEnt));
311 RgSchDlHqEnt *rgSCHDhmHqEntInit(RgSchCellCb *cell)
314 Inst inst = cell->instIdx;
316 /* Init the HARQ data structure */
317 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
319 DU_LOG("\nERROR --> SCH: rgSCHDhmHqEntInit hqE alloc fail");
323 /* Init the HARQ processes */
324 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
325 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
326 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
328 DU_LOG("\nERROR --> SCH: rgSCHDhmHqEntInit hqP alloc fail in hqE");
332 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
336 rgSCHLaaInitDlHqProcCb (cell, hqE);
339 /* Initialize maximum tranmission counter */
340 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
343 /* MW_WORKAROUND for ccpu00122893 */
344 rgSCHDhmHqEntReset(hqE);
350 } /* rgSCHDhmHqEntInit */
353 * @brief This function gets an available HARQ process.
357 * Function: rgSCHDhmGetAvlHqProc
358 * Purpose: This function returns an available HARQ process in
359 * the DL direction. All HARQ processes are maintained
360 * in queues of free and inuse.
362 * 1. Check if the free queue is empty. If yes, return
364 * 2. If not empty, update the proc variable with the
365 * first process in the queue. Return ROK.
367 * Invoked by: scheduler
369 * @param[in] RgSchUeCb *ue
370 * @param[in] CmLteTimingInfo timingInfo
371 * @param[out] RgSchDlHqProc **hqP
373 * -#ROK if successful
374 * -#RFAILED otherwise
377 S16 rgSCHDhmGetAvlHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo,RgSchDlHqProcCb **hqP)
379 RgSchDlHqEnt *hqE = NULLP;
380 RgSchDlHqProcCb *tmpHqProc;
383 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
387 DU_LOG("\nERROR --> SCH : rgSCHDhmGetAvlHqProc hqE NULL ue %d"
393 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
397 DU_LOG("\nERROR --> SCH : rgSCHDhmGetAvlHqProc free %d inUse %d ue %d"
398 , hqE->free.count, hqE->inUse.count, ue->ueId);
399 /* No Harq Process available in the free queue. */
403 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
406 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
408 if (ue->dl.isSpsHqPInUse)
410 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
412 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
417 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
421 /* No Harq Process available in the free queue. */
428 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
429 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
430 tmpHqProc->hasDcch = FALSE;
431 tmpHqProc->cwSwpEnabled = FALSE;
433 /* Remove the element from the free Queue */
434 //cmLListDelFrm(&hqE->free, tmp);
435 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
437 /* Add the element into the inUse Queue as well */
438 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
439 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
444 rgSCHLaaResetDlHqProcCb(tmpHqProc);
448 tmpHqProc->tbSizeAtEstimate[0] = 0;
449 tmpHqProc->tbSizeAtEstimate[1] = 0;
450 tmpHqProc->tbSizeAtFnlz[0] = 0;
451 tmpHqProc->tbSizeAtFnlz[1] = 0;
452 tmpHqProc->tbSizeOfMvdTb[0] = 0;
453 tmpHqProc->tbSizeOfMvdTb[1] = 0;
454 tmpHqProc->itbsAtEstimate[0] = 0;
455 tmpHqProc->itbsAtEstimate[1] = 0;
456 tmpHqProc->prbAtEstimate = 0;
459 } /* rgSCHDhmGetAvlHqProc */
463 * @brief This function adds HARQ process for a given TB in to
464 * the inuse queue upon retx.
468 * Function: rgSCHDhmHqTbRetx
469 * Purpose: This function handles when a HARQ process is scheduled
470 * for retransmission. It adds the HARQ procss to inuse
472 * 1. Check if this HqP is already added to the inUse
473 * queue as part of this function call for other
474 * TB's retransmission.
475 * 2. If already present in inUse Q then do not add.
477 * Invoked by: scheduler
479 * @param[in] RgSchDlHqEnt *hqE
480 * @param[in] CmLteTimingInfo timingInfo
481 * @param[out] RgDlHqProc *hqP
482 * @param[in] uint8_t tbIdx
486 Void rgSCHDhmHqTbRetx(RgSchDlHqEnt *hqE,CmLteTimingInfo timingInfo,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
488 uint8_t othrTbIdx = tbIdx ^ 1;
490 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
492 if (hqE->msg4Proc == hqP)
496 /* fix for ccpu00118633 No Hq proc Avl end*/
498 /* Extra:check if Harq process is already linked to in-use
499 Queue by means of other TB handling. */
500 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
503 if (hqE->msg4Proc != hqP)
505 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
506 rgSCHDhmHqPAdd2InUseLst(hqP);
510 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
513 } /* rgSCHDhmHqTbRetx */
516 * @brief This function returns last scheduled HARQ process for
517 * a UE's HARQ entity.
521 * Function: rgSCHDhmLastSchedHqProc
522 * Purpose: This function returns the last (most recent)
523 * process in the inUse list, which corresponds
524 * to the last scheduled process. Returns NULLP
526 * The reason for introducing this is to have
527 * an ability to check if UE was scheduled
528 * in the current subframe (scheduling would
529 * have caused a proc to be added to the end
530 * of the list, and checking time (only subframe
531 * number probably works) would confirm this.
533 * Invoked by: scheduler
535 * @param[in] RgSchDlHqEnt *hqE
536 * @return RgSchDlHqProcCb *
539 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(RgSchDlHqEnt *hqE)
541 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
542 * until RACH procedure is completed */
543 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
547 return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
548 } /* rgSCHDhmLastSchedHqProc */
552 * @brief This function gets an available HARQ process for MSG 4.
556 * Function: rgSCHDhmGetCcchSduHqProc
557 * Purpose: This function returns an available HARQ process in
558 * the DL direction. All HARQ processes are maintained
559 * in queues of free and inuse.
561 * 1. Check if the free queue is empty. If yes, return
563 * 2. If not empty, update the proc variable with the
564 * first process in the queue. Return ROK.
566 * Invoked by: scheduler
568 * @param[in] RgSchRaCb *raCb
569 * @param[in] CmLteTimingInfo timingInfo
570 * @param[out] RgSchDlHqProcCb **hqP
572 * -#ROK if successful
573 * -#RFAILED otherwise
576 S16 rgSCHDhmGetCcchSduHqProc
579 CmLteTimingInfo timingInfo,
580 RgSchDlHqProcCb **hqP
583 RgSchDlHqProcCb *tmpHqProc;
587 hqE = ueCb->cellInfo[0]->hqEnt;
588 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
591 /* No Harq Process available in the free queue. */
595 /* Remove the element from the free Queue and */
596 /* set the MSG 4 HARQ proc pointer */
597 //cmLListDelFrm(&hqE->free, tmp);
599 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
601 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
603 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
604 /* Fix : syed minor code reorg */
606 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
608 hqE->ccchSduProc = tmpHqProc;
609 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
610 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
613 } /* rgSCHDhmGetCcchSduHqProc */
617 * @brief This function gets an available HARQ process for MSG 4.
621 * Function: rgSCHDhmGetMsg4HqProc
622 * Purpose: This function returns an available HARQ process in
623 * the DL direction. All HARQ processes are maintained
624 * in queues of free and inuse.
626 * 1. Check if the free queue is empty. If yes, return
628 * 2. If not empty, update the proc variable with the
629 * first process in the queue. Return ROK.
631 * Invoked by: scheduler
633 * @param[in] RgSchRaCb *raCb
634 * @param[in] CmLteTimingInfo timingInfo
635 * @param[out] RgDlHqProc **hqP
637 * -#ROK if successful
638 * -#RFAILED otherwise
641 S16 rgSCHDhmGetMsg4HqProc(RgSchRaCb *raCb,CmLteTimingInfo timingInfo)
643 RgSchDlHqProcCb *tmpHqProc;
648 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
651 /* No Harq Process available in the free queue. */
655 /* Remove the element from the free Queue and */
656 /* set the MSG 4 HARQ proc pointer */
657 //cmLListDelFrm(&hqE->free, tmp);
658 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
659 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
660 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
661 hqE->msg4Proc = tmpHqProc;
664 } /* rgSCHDhmGetMsg4HqProc */
667 * @brief This function releases a HARQ process.
671 * Function: rgSCHDhmRlsHqpTb
672 * Purpose: This function resets the TB specific fields
673 * Based on the other TBs state, this HqProcess
674 * is returned to the HqEnt.
676 * 1. Add the HARQ process to the free queue.
677 * Invoked by: scheduler and HARQ processing
679 * @param[in] RgDlHqProc *hqP
680 * @param[in] uint8_t tbIdx
681 * @param[in] Bool togNdi
685 Void rgSCHDhmRlsHqpTb(RgSchDlHqProcCb *hqP,uint8_t tbIdx,Bool togNdi)
688 uint8_t othrTbIdx = tbIdx ^ 1;
690 RgSchCmnDlHqProc *cmnHqDl;
694 RgSchDlLcCb* lcCb = NULLP;
698 /* Reset all tbInfo values */
703 if (hqP->hqE->ue != NULLP)
705 RgSchUeCb *ueCb = hqP->hqE->ue;
706 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
707 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
708 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
709 /* to get retransmission, decreasing transmission counter */
710 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
711 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
712 static uint32_t retxCnt1 = 0;
714 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
715 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
720 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
723 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
726 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
729 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
732 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
733 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
734 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
735 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
736 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
738 retxCnt1 += numDlRetx;
740 #endif /* MAC_SCH_STATS */
741 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
745 hqP->tbInfo[tbIdx].ndi ^= 1;
750 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
752 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
753 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
755 if (lcCb->lcType == CM_LTE_LCH_DTCH)
757 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
759 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
762 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
764 lcCb->qciCb->dlUeCount--;
772 hqP->tbInfo[tbIdx].tbSz = 0;
773 hqP->tbInfo[tbIdx].numLch = 0;
774 hqP->tbInfo[tbIdx].txCntr = 0;
775 /* FOR ACK NACK REP */
776 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
777 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
778 hqP->tbInfo[tbIdx].ackCount = 0;
779 /* pdcch is moved from TbCb to HqCb.
780 This pdcch will be set to NULL when
781 HqCb will be pushed to free list*/
782 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
783 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
784 hqP->tbInfo[tbIdx].nackCount = 0;
785 hqP->tbInfo[tbIdx].dtxCount = 0;
786 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
787 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
789 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
791 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
792 /* Handling msg4 hqProc */
793 if (hqE->msg4Proc == hqP)
795 hqE->msg4Proc = NULLP;
798 /* Add the proc to the free list */
799 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
800 rgSCHDhmHqPAdd2FreeLst(hqP);
804 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
805 * is dangerous and it expects ccchSduProc is the first
806 * DL allocation for a UE, and considering a scenario
807 * of multiple UEs contending and 1 UE per TTI, this
808 * assumption can be wronged, leading to inUse list
809 * corruption. Hence altering this check.
810 * A better approach would be do avoid having this
811 * special handling for ccchSduProc, streamline
812 * it with the usual approach. */
813 if (hqE->ccchSduProc == hqP)
815 hqE->ccchSduProc = NULLP;
816 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
817 * in inUse list, Hence need not to delete from inUse list*/
818 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
820 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
821 rgSCHDhmHqPDelFrmInUseLst(hqP);
825 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
829 /* Add the proc to the free list */
830 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
831 rgSCHDhmHqPAdd2FreeLst(hqP);
836 /* extra:check if other TB is also free for allocation then
837 * add it to FREE List */
838 switch(hqP->tbInfo[othrTbIdx].state)
841 /* Remove the element from the inUse Queue */
842 /* Freeing up the HARQ proc blocked for
843 * indefinite time in case of Retx */
844 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
846 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
847 rgSCHDhmHqPDelFrmInUseLst(hqP);
852 rgEmtcsetNullSubFrm(hqP);
854 /* Add the proc to the free list */
855 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
856 rgSCHDhmHqPAdd2FreeLst(hqP);
858 if (hqE->free.count > 8)
861 printf("\nDEBUG --> SCH: Crashing invalid hq count after free \n");
862 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
867 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
870 cmnHqDl->spsAction = 0;
871 cmnHqDl->isSpsActv = FALSE;
872 cmnHqDl->isSpsSvcSchd = FALSE;
877 /* Remove the element from the inUse Queue */
878 /* Freeing up the HARQ proc blocked for
879 * indefinite time in case of Retx */
880 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
882 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
883 rgSCHDhmHqPDelFrmInUseLst(hqP);
891 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
894 } /* rgSCHDhmRlsHqpTb */
897 * @brief This function releases a HARQ process.
901 * Function: rgSCHDhmRlsHqProc
902 * Purpose: This function returns a HARQ process to HARQ Entity
903 * in the DL direction.
905 * 1. Add the HARQ process to the free queue.
906 * Invoked by: scheduler and HARQ processing
908 * @param[in] RgDlHqProc *hqP
912 Void rgSCHDhmRlsHqProc(RgSchDlHqProcCb *hqP)
917 /* THIS FUNCTION IS NOT CALLED */
918 if (hqP->hqE->ue != NULLP)
920 RgSchUeCb *ueCb = hqP->hqE->ue;
921 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
922 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
923 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
924 /* to get retransmission, decreasing transmission counter */
925 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
926 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
928 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
933 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
936 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
939 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
942 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
945 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
946 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
947 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
948 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
949 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
951 #endif /* MAC_SCH_STATS */
955 rgEmtcsetNullSubFrm(hqP);
957 rgSCHDhmHqPDelFrmInUseLst(hqP);
958 rgSCHDhmHqPAdd2FreeLst(hqP);
964 } /* rgSCHDhmRlsHqProc */
968 * @brief This function gets HARQ process with the given ID.
972 * Function: rgSCHDhmGetHqProcFrmId
973 * Purpose: This function returns the HARQ process with the given ID.
976 * @param[in] RgSchUeCb *ue
977 * @param[in] uint8_t idx
978 * @param[in] RgDlHqProc **hqP
980 * -# ROK if successful
981 * -# RFAILED otherwise
984 S16 rgSCHDhmGetHqProcFrmId(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t idx,RgSchDlHqProcCb **hqP)
988 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
989 /* Pick the proc based on the index provided */
990 *hqP = &(hqE->procs[idx]);
993 } /* rgSCHDhmGetHqProcFrmId */
996 * @brief This function gets SPS HARQ process from the given time
1000 * Function: rgSCHDhmSpsDlGetHqProc
1001 * Purpose: This function returns the SPS HARQ process for the given time
1003 * @param[in] RgSchUeCb *ue
1004 * @param[in] CmLteTimingInfo timingInfo
1005 * @return RgSchDlHqProcCb control block
1008 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
1012 RgSchDlHqProcCb *hqProc = NULLP;
1013 CmLList *tmp = NULLP;
1015 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1017 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1021 /* No Harq Process available in the free queue. */
1025 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1026 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1029 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1031 /* If the HARQ process is in the free list, retrieve the process */
1032 while (hqProc->procId != idx)
1034 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1039 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1044 /* No Harq Process available in the free queue. */
1048 hqProc->tbInfo[0].timingInfo = timingInfo;
1049 hqProc->tbInfo[1].timingInfo = timingInfo;
1051 /* Remove the element from the free Queue */
1052 //cmLListDelFrm(&hqE->free, tmp);
1053 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1055 /* Add the element into the inUse Queue as well */
1056 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1057 rgSCHDhmHqPAdd2InUseLst(hqProc);
1060 rgSCHLaaResetDlHqProcCb(hqProc);
1064 } /* rgSCHDhmSpsDlGetHqProc */
1065 #endif /* LTEMAC_SPS */
1068 /** * @brief Handler for handling TA.
1072 * Function : rgSCHDhmFdbkIndHndlTa
1074 * This function handles the TA state and values based on the
1075 * feedback indication received.
1077 * @param[in] RgSchDlHqProcCb *hqP
1078 * @param[in] uint8_t tbIdx
1079 * @param[in] uint8_t fdbk
1083 static Void rgSCHDhmFdbkIndHndlTa(RgSchDlHqProcCb *hqP,uint8_t tbIdx,uint8_t fdbk,Bool maxHqRetxReached)
1088 ueCb = hqP->hqE->ue;
1093 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1094 hqP->tbInfo[tbIdx].taSnt = FALSE;
1095 /* To prevent duplicate inserts of ueCb into TA list */
1096 if (ueCb->taLnk.node == NULLP)
1098 ueCb->taLnk.node = (PTR)ueCb;
1099 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1104 DU_LOG("\nERROR --> SCH : Trying to add CRNTI:%d into TA"
1105 "ACK List twice", ueCb->ueId);
1111 /* If Ta was sent and its the final NACK, then reset only the
1112 * taState to IDLE and not the value */
1113 /* Changed handling in case maxhqretx is reached for TA */
1114 if(TRUE == maxHqRetxReached)
1116 hqP->tbInfo[tbIdx].taSnt = FALSE;
1117 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1119 rgSCHUtlReTxTa(cell, ueCb);
1120 DU_LOG("\nERROR --> SCH : Nack Rcvd for TA. Max Tries Attempted");
1124 /* If Ta was sent and its the final NACK, then reset only the
1125 * taState to IDLE and not the value */
1126 if(TRUE == maxHqRetxReached)
1128 hqP->tbInfo[tbIdx].taSnt = FALSE;
1129 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1131 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1132 * issue for VoLTE call */
1133 rgSCHUtlDlTARpt(cell, ueCb);
1142 } /* rgSCHDhmFdbkIndHndlTa */
1144 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1145 /** * @brief Handler for scheduling TA.
1149 * Function : rgSCHDhmShcdTa
1151 * This function is called by scheduler when resource allocation
1152 * for TA transmission is done.
1154 * @param[in] RgSchUeCb *ue
1155 * @param[out] RgSchDlHqTbCb *tbInfo
1159 Void rgSCHDhmSchdTa(RgSchUeCb *ueCb,RgSchDlHqTbCb *tbInfo)
1162 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1163 ueCb->dl.taCb.numRemSf = 2;
1164 tbInfo->schdTa.pres = PRSNT_NODEF;
1165 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1168 } /* rgSCHDhmSchdTa */
1171 /** * @brief Handler for fetching Harq Proc given the feeback information.
1175 * Function : rgSCHDhmHqProcByFdbkTime
1177 * This function shall fetch all the harq proc having the feedback
1178 * timing information.
1180 * @param[in] RgSchDlHqEnt *hqE
1181 * @param[in] CmLteTimingInfo timeInfo
1182 * @param[in] Bool *isMsg4
1183 * @param[out] RgSchDlHqProcCb **hqPrcs
1184 * @param[out] uint8_t *numTbs
1185 * @param[out] S8 *tbStrtIdx
1186 * @param[out] uint8_t *cntHqPrcs
1189 static S16 rgSCHDhmHqProcByFdbkTime
1192 CmLteTimingInfo timeInfo,
1194 RgSchDlHqProcCb **hqPrcs,
1201 RgSchDlHqTbCb *tbCb;
1202 RgSchDlHqProcCb *hqP;
1203 CmLteTimingInfo schdSfTime;
1204 RgSchTddDlAscSetIdxK ascIdx;
1215 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1218 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1219 tbStrtIdx[*cntHqPrcs] = 0;
1220 numTbs[*cntHqPrcs] = 1;
1225 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1226 noFdbks = ascIdx.numFdbkSubfrms;
1228 for(idx=0; idx<noFdbks; idx++)
1230 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1231 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1232 * serving the purpose */
1233 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1234 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1235 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1239 hqP = (RgSchDlHqProcCb*)node->node;
1242 numTbs[*cntHqPrcs] = 0;
1243 tbStrtIdx[*cntHqPrcs] = -1;
1244 for (i = 0; i < 2; i++)
1246 /* Extra:check which TB is waiting for feedback */
1247 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1249 if (tbStrtIdx[*cntHqPrcs] == -1)
1251 tbStrtIdx[*cntHqPrcs] = i;
1253 numTbs[*cntHqPrcs]++;
1256 if (numTbs[*cntHqPrcs] > 0)
1258 hqPrcs[*cntHqPrcs] = hqP;
1263 /* AN REP Hq Procs */
1264 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1267 tbCb = (RgSchDlHqTbCb *)(node->node);
1270 numTbs[*cntHqPrcs] = 0;
1271 tbStrtIdx[*cntHqPrcs] = -1;
1272 for (i = 0; i < 2; i++)
1274 /* Extra:check which TB is waiting for feedback */
1275 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1277 if (tbStrtIdx[*cntHqPrcs] == -1)
1279 tbStrtIdx[*cntHqPrcs] = i;
1281 numTbs[*cntHqPrcs]++;
1284 if (numTbs[*cntHqPrcs] == 2)
1288 if (numTbs[*cntHqPrcs] > 0)
1290 hqPrcs[*cntHqPrcs] = hqP;
1302 /** * @brief Handler for fetching Harq Proc given the timming information.
1306 * Function : rgSCHDhmHqProcByTime
1308 * This function shall fetch the harq proc using the timing information.
1310 * @param[in] RgSchDlHqEnt *hqE
1311 * @param[in] CmLteTimingInfo timeInfo
1312 * @param[in] Bool *isMsg4
1313 * @param[out] uint8_t *numTbs
1314 * @param[out] S8 *tbStrtIdx
1315 * @return RgSchDlHqProcCb*
1316 * -# RgSchDlHqProcCb*
1319 RgSchDlHqProcCb *rgSCHDhmHqProcByTime(RgSchDlHqEnt *hqE,CmLteTimingInfo timeInfo,Bool *isMsg4,RgSchDlSf *sf)
1323 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1326 return (hqE->msg4Proc);
1334 /** * @brief Handler for handling the harq transaction failure.
1338 * Function : rgSCHDhmHqTbTrnsFail
1340 * This function handled the harq TB transaction failure :
1341 * - If retries have not reached maximum, add to the reTx Q.
1342 * - else do error recovery.
1344 * @param[in] RgSchCellCb *cell
1345 * @param[in] RgSchDlHqProcCb *hqP
1346 * @param[in] uint8_t tbCnt
1347 * @param[out] Bool *isMaxRetx
1352 Void rgSCHDhmHqTbTrnsFail(RgSchCellCb *cell,RgSchDlHqProcCb *hqP,uint8_t tbCnt,Bool *isMaxRetx)
1359 /* Fetch the maximum number of harq transmissions */
1360 if (hqE->msg4Proc == hqP)
1363 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1365 DU_LOG("\nDEBUG --> SCH : rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1366 hqP->hqE->raCb->tmpCrnti);
1367 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1371 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1375 maxHqTx = hqE->maxHqTx;
1378 #ifdef MAC_SCH_STATS
1379 if (hqE->ue != NULLP)
1381 RgSchUeCb *ueCb = hqE->ue;
1382 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1383 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1384 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1385 static uint32_t retxCnt = 0;
1389 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1391 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1392 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1394 #endif /* MAC_SCH_STATS */
1396 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1397 /* Reset the PDCCH reference */
1399 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1401 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1403 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1406 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1407 * for the UE. Addtion to the retransmission queue will be done on
1408 * HARQ RTT timer expiry.--*/
1409 switch(hqP->tbInfo[tbCnt ^ 1].state)
1412 /*As the first TB is ACKED we have not started HARQ RTT for the
1413 * HqP, so start it here.*/
1414 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1415 rgSCHDhmHqPDelFrmInUseLst(hqP);
1417 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1420 /* Integration fix */
1421 /* Setting cntrRetxAllocFail to MAX value here */
1422 /* Since the hqP entry is already deleted from inUse list of HqEntity
1423 setting the value here will ensure the entry is not deleted
1424 again during release harq proc */
1425 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1426 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1428 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1429 if (hqP->tbInfo[1].txCntr)
1431 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1437 /*As the first TB is NACKED we have already started HARQ RTT for the
1438 * HqP, so dont start it here, just delete from in use queue.*/
1439 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1440 rgSCHDhmHqPDelFrmInUseLst(hqP);
1443 /*As this is the first TB to be fed back and is NACKED start
1444 * the HARQ RTT here.*/
1446 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1452 /* extra:check if already removed as part of other TB processing
1453 * then donot remove from InUse Q */
1454 /* Check if other TB is not waiting for feedback.
1455 * Makinf sure hqP is present in inUse Queue until
1456 * it is fedback for all its TBs */
1457 switch(hqP->tbInfo[tbCnt ^ 1].state)
1460 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1461 if(hqE->msg4Proc != hqP)
1463 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1464 rgSCHDhmHqPDelFrmInUseLst(hqP);
1466 /* Retransmission needs to be done. Add to the scheduler Q */
1467 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1470 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1471 if(hqE->msg4Proc != hqP)
1473 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1474 rgSCHDhmHqPDelFrmInUseLst(hqP);
1478 /* Retransmission needs to be done. Add to the scheduler Q */
1480 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1488 /* Failure Notification */
1489 if (hqE->msg4Proc == hqP)
1491 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1492 rgNumMsg4FailMaxRetx++;
1494 hqE->cell->tenbStats->sch.msg4Fail ++;
1497 /* Perform RAM MSG4 done processing */
1498 DU_LOG("\nDEBUG --> SCH : rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1499 hqP->hqE->raCb->tmpCrnti);
1500 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1504 /* Release the Harq Proc */
1505 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1511 } /* rgSCHDhmHqTbTrnsFail */
1513 uint32_t rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1514 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1517 /** * @brief Function to decode the position of HarqFb for M=1.
1521 * Function : rgSchGetHqFdbkPosForM1
1523 * @param[in] RgSchUeCb *ue,
1524 * @param[in] RgSchDlHqProcCb *hqP,
1525 * @param[in] uint8_t *isAck,
1526 * @param[in] RgTfuHqInfo *fdbk,
1527 * @param[in] uint8_t tbIdx,
1528 * @param[in] RgSchTddANInfo *anInfo;
1531 static Void rgSchGetHqFdbkPosForM1
1534 RgSchDlHqProcCb *hqP,
1538 RgSchTddANInfo *anInfo
1543 /* handle pusch and pucch cases */
1544 /* PUSCH:: Fdbks are in the increasing order
1545 * of servCellIdx as per 36.212 section 5.2.26*/
1546 switch(ue->f1bCsAVal)
1548 case RG_SCH_A_VAL_2:
1550 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1552 *isAck = fdbk->isAck[1];/*SCell*/
1556 *isAck = fdbk->isAck[0];/*PCell*/
1560 case RG_SCH_A_VAL_3:
1562 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1564 uint8_t cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1565 hqP->hqE->cell->cellId,
1568 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1569 {/*SCell - mimo mode*/
1570 if(TRUE == fdbk->isPusch)
1572 *isAck = fdbk->isAck[tbIdx + 1];
1576 *isAck = fdbk->isAck[tbIdx];
1580 {/*SCell - siso mode*/
1581 *isAck = fdbk->isAck[2];
1585 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1586 {/*Primary Cell - mimo mode*/
1587 *isAck = fdbk->isAck[tbIdx];
1590 {/*Primary Cell - siso mode*/
1591 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1593 /* If fdbk is on PUSCH but its not an SPS occasion*/
1594 *isAck = fdbk->isAck[0];
1598 /* If fdbk is on PUCCH or its an SPS occasion*/
1599 *isAck = fdbk->isAck[2];
1605 case RG_SCH_A_VAL_4:
1607 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1609 *isAck = fdbk->isAck[tbIdx + 2];
1613 *isAck = fdbk->isAck[tbIdx];
1622 }/* End of rgSchGetHqFdbkPosForM1 */
1624 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1628 * Function : rgSchGetHqFdbkPosForM234
1630 * @param[in] RgSchUeCb *ue,
1631 * @param[in] RgSchDlHqProcCb *hqP,
1632 * @param[in] uint8_t *isAck,
1633 * @param[in] RgTfuHqInfo *fdbk,
1634 * @param[in] uint8_t tbIdx,
1635 * @param[in] RgSchTddANInfo *anInfo;
1636 * @param[in] CmLteTimingInfo timeInfo;
1639 static Void rgSchGetHqFdbkPosForM234
1642 RgSchDlHqProcCb *hqP,
1646 RgSchTddANInfo *anInfo,
1648 CmLteTimingInfo timeInfo
1653 RgSchTddANInfo *pCellAnInfo;
1658 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1659 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1661 if(TRUE == fdbk->isPusch)
1665 if (anInfo->wUlDai == 3)
1667 incr = anInfo->wUlDai;
1673 if(1 == anInfo->ulDai)
1675 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1676 hqP->tbInfo[tbIdx].tbIdx + incr;
1680 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1685 if(1 == anInfo->ulDai)
1687 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1689 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1693 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1698 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1706 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1707 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1713 /* SPS occasion feedback in case of M > 2 will
1714 * be always present in the index 0*/
1716 if(hqP->spsN1PucchRes.pres == TRUE)
1717 {/* SPS occasion hq proc */
1721 if((NULLP != pCellAnInfo) &&
1722 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1724 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1726 {/* NO SPS occasion was present in the bundle*/
1727 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1732 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1736 *isAck = fdbk->isAck[fdbkIdx];
1738 static RgSchDlHqProcCb *temp = NULLP;
1739 if (temp != hqP->tbInfo[tbIdx].hqP)
1741 statsCnt = statsCnt % 10000;
1742 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
1743 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
1744 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot;
1745 dlHqStats[statsCnt].ack = *isAck;
1746 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
1747 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;
1749 dlHqStats[statsCnt].ulDai = incr;
1750 if(TRUE == fdbk->isPusch)
1752 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
1756 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1760 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
1761 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
1762 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
1763 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
1764 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
1765 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
1766 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
1767 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
1770 temp = hqP->tbInfo[tbIdx].hqP;
1775 }/*rgSchGetHqFdbkPosForM234*/
1779 * @brief Handler for HARQ feedback received for DL transmission.
1783 * Function : rgSCHDhmHqFdbkInd
1785 * This function shall act on the feedback received from TOM for DL
1786 * transmission. If the feedback for msg4 is final (after max transmissions
1787 * or ACK) inform RAM that Msg4 transmission is done.
1790 * @param[in] Void *cb
1791 * @param[in] uint8_t cbType
1792 * @param[in] RgSchCellCb cellCb
1793 * @param[in] CmLteTimingInfo timeInfo
1794 * @param[in] TfuHqInfo *fdbk
1795 * @param[in] RgInfRlsHqInfo *rlsHqBufs
1796 * @param[in] RgSchErrInfo *err
1801 S16 rgSCHDhmHqFdbkInd
1805 RgSchCellCb *cellCb,
1806 CmLteTimingInfo timeInfo,
1808 RgInfRlsHqInfo *rlsHqBufs,
1812 RgSchCellCb *sCell = NULLP;
1814 /*ccpu00127339 - MOD - change to avoid the crash*/
1815 RgSchUeCb *ue = NULLP;
1817 Bool isMsg4 = FALSE;
1818 RgSchRaCb *raCb = NULLP;
1820 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
1821 * given feedback at a time */
1822 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
1823 uint8_t numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
1824 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
1827 RgSchTddANInfo *anInfo = NULLP;
1830 RgrTddAckNackMode ackNackMode;
1832 RgSchDlSf *nxtDlsf = NULLP;
1833 /* uint8_t rcvCnt = 0; */
1834 CmLteTimingInfo nxtfrm = {0,0};
1836 Bool maxHqRetxReached;
1838 Bool hasRelPdcch = FALSE;
1841 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1842 RgSchTddDlAscSetIdxK ascIdx;
1846 #ifdef LTEMAC_SPS_AN_MUX
1847 Bool isPusch = FALSE;
1850 /* Subframes in which transmissions are scheduled and whose feedback can come
1851 * in this subframe. Used only for Multiplexing mode */
1852 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
1853 #ifdef RGSCH_SPS_STATS
1854 RgSchCmnDlHqProc *cmnHqDl;
1858 uint8_t sCellActCePres = 0;
1860 /* LTEMAC_SPS_AN_MUX*/
1861 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
1863 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
1865 raCb = (RgSchRaCb *)(cb);
1866 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
1868 /* ccpu00139061 Fix */
1869 rnti = raCb->tmpCrnti;
1873 ue = (RgSchUeCb *)(cb);
1874 ackNackMode = ue->dl.ackNackMode;
1875 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
1877 #ifdef LTEMAC_SPS_AN_MUX
1878 isPusch = fdbk->isPusch;
1882 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
1889 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1890 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
1891 noFdbks = ascIdx.numFdbkSubfrms;
1893 #ifdef LTEMAC_SPS_AN_MUX
1894 /* Calculate the subframe time at which transmissions should have happened to
1895 * receive feedback in this subframe */
1896 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
1898 for(idx=0; idx<noFdbks; idx++)
1900 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1901 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1902 * serving the purpose */
1903 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
1908 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
1909 tbStrtIdx, &hqCnt,hqE->cell);
1910 /* Fetch the harqProc from the inUse list */
1912 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
1916 err->errType = RGSCHERR_DHM_FDBK_IND;
1917 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
1921 /* ccpu00147469 : This code is moved below as here this code always try to
1922 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
1926 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
1928 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
1934 #ifdef LTEMAC_SPS_AN_MUX
1935 /* Check if feedback came on configured UL SPS grant in Muxing mode */
1936 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
1940 /* Pick the valid feedbacks out of M feedbacks */
1941 for(idx=0; idx<noFdbks; idx++)
1943 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
1944 * and no release pdcch is sent in prevTime */
1945 /* TODO: SPS_TDD: Check this while testing */
1946 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
1947 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
1948 schdSfTime[idx])) &&
1949 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
1951 /* Discard the feedback which is corresponding to a subframe in
1952 * which no DL transmission took place */
1954 while(tmpIdx < noFdbks)
1956 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1957 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1963 } /* end of for loop */
1964 } /* end of configured UL SPS grant check */
1976 for(idx=0;idx < hqCnt; idx++)
1978 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
1982 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
1983 hqPrcs[idx]->hqE->cell->cellId,ue);
1985 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
1989 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
1991 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
1995 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
1996 "Ack Rcvd. No Ack/Nack feedback available \n"));
2001 sCell = hqPrcs[idx]->hqE->cell;
2002 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2003 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2004 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2006 /* Fix : syed MultiUe per TTI crash in TA List. */
2008 maxHqRetxReached = FALSE;
2009 /* Remove the harq process from the subframe */
2010 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2014 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2017 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2019 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2020 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2022 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2026 /* TODO: review for TM4 and CA interaction */
2027 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2029 isAck = fdbk->isAck[!tbCnt];
2033 isAck = fdbk->isAck[tbCnt];
2042 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2046 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2052 /* revanth tweakin AN PUSCH to ACK always */
2053 if (hqPrcs[idx]->isPuschFdbk)
2059 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2060 if(cellCb->ulDlCfgIdx != 5)
2062 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2063 cellCb, sf, &nxtDlsf, &nxtfrm);
2065 /* Keep a tab on how many ACKs or NACKs we have received */
2066 if (isAck == TFU_HQFDB_ACK)
2068 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2069 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2071 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2072 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2074 /* Do not update the Ul Trans Time in case of raCb */
2077 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2079 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2083 else if (isAck == TFU_HQFDB_NACK)
2085 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2086 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2088 sCell->tenbStats->sch.dlNack[tbCnt]\
2089 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2090 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2091 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2093 /* Do not update the Ul Trans Time in case of raCb */
2096 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2098 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2099 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2103 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2105 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2111 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2113 sCell->tenbStats->sch.dlDtx[tbCnt]\
2114 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2117 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2121 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2123 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2128 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2130 if(isAck == TFU_HQFDB_ACK)
2132 gSCellTb1AckCount++;
2133 gSCellTb2AckCount++;
2134 }else if(isAck == TFU_HQFDB_NACK)
2136 gSCellTb1NackCount++;
2137 gSCellTb2NackCount++;
2140 gSCellTb1DtxCount++;
2141 gSCellTb2DtxCount++;
2146 if(isAck == TFU_HQFDB_ACK)
2148 gPCellTb1AckCount++;
2149 gPCellTb2AckCount++;
2150 }else if(isAck == TFU_HQFDB_NACK)
2152 gPCellTb1NackCount++;
2153 gPCellTb2NackCount++;
2156 gPCellTb1DtxCount++;
2157 gPCellTb2DtxCount++;
2161 /* Check if this is repeating UE */
2162 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2164 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2165 /* Check if last repetition */
2166 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2168 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2169 /* Update feedback time for this hqP TB so that
2170 * next subframe its picked up */
2171 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2173 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2174 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2178 /* For a repeating UE take the decision here */
2179 /* For a repeating UE take the decision here */
2180 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2181 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2183 isAck = TFU_HQFDB_ACK;
2185 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2186 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2188 isAck = TFU_HQFDB_DTX;
2192 isAck = TFU_HQFDB_NACK;
2194 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2198 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2201 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2202 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2203 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2206 /* ACK or NACK received for SPS ACTV PDCCH
2207 * Hence consider SPS ACTVN PDCCH received successfully */
2208 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2211 if(TFU_HQFDB_ACK == isAck)
2218 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2220 /* Inform Random Access Module regarding the ack received */
2223 /*RRC Connection Setup failure issue where RRC connection
2224 * setup was not reaching UE due to message 4 HARQ failure */
2225 #ifdef XEON_SPECIFIC_CHANGES
2226 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2228 rgSCHRamMsg4Done(cellCb, raCb);
2231 else /*ccpu00114124- HARQ Release for Msg4 */
2234 /*Update feedback history for every Tx/Retx */
2235 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2237 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2238 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2240 /* Store activation CE presence as it is required later to start
2241 *activation delay timer */
2242 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2244 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2250 /* If this Msg4 DTX, there will be
2251 * no DlHqProc as it has its own HarqProc */
2254 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2255 maxHqRetxReached = hqRls;
2257 if ((isMsg4 == FALSE))
2259 /*Update feedback history for every Tx/Retx */
2260 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2263 if (isMsg4 == FALSE)
2265 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2266 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2273 /* MS_WORKAROUND: to increase Harq Fail Counter .
2274 The status field is required for tracking the number of harq faliures at MAC*/
2277 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2278 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2282 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2283 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2285 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2286 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2287 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2291 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2293 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2296 /* Handle Scell activation */
2297 if (TRUE == sCellActCePres)
2299 /* Primary Cellcb needs to be retrived
2300 * if the feedback is coming on pusch of
2301 * sec cell. THis needs to be considered
2303 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2309 hqPrcs[idx]->cwSwpEnabled = FALSE;
2311 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2313 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2314 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2315 hqPrcs[idx]->procId;
2316 rlsHqBufs->numUes++;
2319 hqPrcs[idx]->isPuschFdbk = 0;
2324 /*it is possible for some TDD configurations (like TDD cfg 5)
2325 * to have multiple feedback for 13 subframes before. It is
2326 * possible in such a case to have a release sent after data
2327 * thus running into a situation where we are receiving feedback
2328 * for both data and relese pdcch
2331 if ( (hqCnt == 0) ||
2332 (hasRelPdcch && rcvCnt > hqCnt)
2335 if (ue && hasRelPdcch)
2337 /* Bool found = FALSE; */
2339 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2349 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2350 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2352 CmLteTimingInfo txTime;
2353 uint8_t ulDlCfgIdx = 0;
2354 uint8_t maxFdbks = 0;
2357 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2359 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2363 for(itr=0; itr< maxFdbks; itr++)
2366 /* Handling the case of only SPS release pdcch
2367 * and no other scheduling in both the serving cells
2369 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2370 {/* Using the sorted K table */
2371 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2372 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2376 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2377 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2380 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2383 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2386 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2388 isAck = fdbk->isAck[0];
2391 isAck = fdbk->isAck[2];
2395 /* M > 1 same below logic apply.
2396 If SPS occasion and rel pdcch is present
2397 SPS occasion after SPS release cannot
2402 isAck = fdbk->isAck[itr];
2405 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2407 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2408 /* Remove release PDCCH from the subframe */
2409 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2410 sf->relPdcch = NULLP;
2420 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2421 /* Remove release PDCCH from the subframe */
2422 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2423 sf->relPdcch = NULLP;
2425 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2428 if ( found == FALSE )
2430 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2431 DU_LOG("\nERROR --> SCH : NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2432 ue->ueId,timeInfo.sfn, timeInfo.slot);
2433 err->errType = RGSCHERR_DHM_FDBK_IND;
2434 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2439 #endif /* LTEMAC_SPS */
2440 /* Initialise the Ack/Nack feedback */
2441 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2442 scheduling. So added a condition !isMsg4 to avoid calling the function
2443 rgSCHUtlInitUeANFdbkInfo*/
2444 if((ue) && (!anUpd) && (!isMsg4))
2447 /* TODO:: Initi the anInfo all the serving cells */
2448 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2450 if(ue->cellInfo[idx])
2452 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2453 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2454 * else don't do anything. basically continue for next serving
2458 rgSCHUtlInitUeANFdbkInfo(anInfo);
2463 rgSCHUtlInitUeANFdbkInfo(anInfo);
2469 //#endif /* LTEMAC_SPS */
2472 /** * @brief Handler for HARQ feedback received for DL transmission.
2476 * Function : rgSCHDhmPrcFdbkForTb
2478 * Process Hq Prc Fdbk for a TB
2480 * @param[in] RgSchCellCb *cell
2481 * @param[in] RgTfuHarqAckIndInfo *fdbk
2482 * @param[in] RgSchErrInfo *err
2487 S16 rgSCHDhmPrcFdbkForTb
2491 RgSchDlHqProcCb *hqP,
2496 CmLteTimingInfo timingInfo,
2498 RgInfRlsHqInfo *rlsHqBufs,
2503 Inst inst = cell->instIdx;
2505 #ifdef RGSCH_SPS_STATS
2506 RgSchCmnDlHqProc *cmnHqDl;
2509 RgSchRaCb *raCb = NULLP;
2511 Bool hqFreed =FALSE;
2512 Bool maxHqRetxReached = FALSE;
2513 RgSchCmnDlUe *ueDl = NULLP;
2514 RgSchCellCb *sCell = hqP->hqE->cell;
2516 RgSchEmtcDlSf *emtcSf;
2517 CmLteTimingInfo frm = timingInfo;
2522 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2525 /* Fix : syed MultiUe per TTI crash in TA List. */
2526 maxHqRetxReached = FALSE;
2528 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2529 * TODO: Need to enhance this in case of TM4 testing,
2530 * when cwSwap flag is considered. */
2532 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2533 tbCnt=%d , isAck=%d",tbCnt,isAck));
2534 if (isAck == TFU_HQFDB_ACK)
2536 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2538 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2539 /* Do not update the Ul Trans Time in case of raCb */
2542 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2544 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2550 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2551 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2556 else if (isAck == TFU_HQFDB_NACK)
2558 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2559 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2560 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2561 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2562 /* Do not update the Ul Trans Time in case of raCb */
2565 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2566 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2568 sCell->tenbStats->sch.dlNack[tbCnt]\
2569 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2576 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2578 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2579 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2582 /* Added Dl TB count for NACKED data*/
2584 if(hqP->tbInfo[tbCnt].txCntr == 1)
2586 cell->dlUlTbCnt.tbTransDlFaulty++;
2592 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2593 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2594 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2597 sCell->tenbStats->sch.dlDtx[tbCnt]\
2598 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2601 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2606 /* Added Dl TB count for DTXED data*/
2608 if(hqP->tbInfo[tbCnt].txCntr == 1)
2610 cell->dlUlTbCnt.tbTransDlFaulty++;
2615 /* Check if this is repeating UE */
2616 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2618 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2625 /* For a Normal UE take the decision here */
2626 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2628 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2631 /* Process either the ACK received or max retries have occurred */
2632 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2633 if (TFU_HQFDB_ACK == isAck)
2637 /* SR_RACH_STATS : MSG4 ACK*/
2642 raCb = rgSCHDbmGetRaCb(cell, rnti);
2644 DU_LOG("\nDEBUG --> SCH: Ack Rcvd. FdbkInd for Msg4Done\n");
2645 /* Inform Random Access Module regarding the ack received */
2648 /*RRC Connection Setup failure issue where RRC connection
2649 * setup was not reaching UE due to message 4 HARQ failure */
2650 printf("\nDEBUG --> SCH: MSG4 Ack ,calling rgSCHRamMsg4Done\n");
2651 ret = rgSCHRamMsg4Done(cell, raCb);
2656 printf("\nDEBUG --> SCH: raCb is NULLP\n");
2659 else /*ccpu00114124- HARQ Release for Msg4 */
2661 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2662 /* Push this harq process back to the free queue */
2663 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2665 if(hqP->tbInfo[tbCnt].txCntr == 1)
2667 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2670 RGSCH_NULL_CHECK(cell->instIdx, ue);
2671 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2672 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2681 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2682 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2684 if(hqP->tbInfo[tbCnt].txCntr == 1)
2686 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2689 RGSCH_NULL_CHECK(cell->instIdx, ue);
2690 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2694 #ifdef XEON_SPECIFIC_CHANGES
2695 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2699 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2700 maxHqRetxReached = hqRls;
2706 /* MS_WORKAROUND: to increase Harq Fail Counter .
2707 The status field is required for tracking the number of harq faliures at MAC*/
2710 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2711 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2714 else if(maxHqRetxReached)
2716 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
2717 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2718 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
2723 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2724 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2726 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2727 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2728 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2732 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
2734 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
2737 } /* rgSCHDhmPrcFdbkForTb */
2738 /** * @brief Function to decode the position of HarqFb for eachCell.
2742 * Function : rgSchGetHqFdbkPos
2744 * @param[in] RgSchCellCb *cell,
2745 * @param[in] RgSchUeCb *ue,
2746 * @param[in] RgSchDlHqProcCb *hqP,
2747 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
2748 * @param[in] Bool *isAck,
2749 * @param[in] RgTfuHqInfo *fdbk,
2752 Void rgSchGetHqFdbkPos
2756 RgSchDlHqProcCb *hqP,
2757 RgrSchFrmt1b3TypEnum uciFrmtTyp,
2762 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2764 isAck[0] = fdbk->isAck[0];
2765 isAck[1] = fdbk->isAck[1];
2769 /* LAA Making all ack for LAA CELL */
2770 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
2780 /* PUSCH:: Fdbks are in the increasing order
2781 * of servCellIdx as per 36.212 section 5.2.26*/
2782 switch(ue->f1bCsAVal)
2784 case RG_SCH_A_VAL_2:
2786 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2788 isAck[0] = fdbk->isAck[1];/*SCell*/
2789 isAck[1] = fdbk->isAck[1];/*SCell*/
2793 isAck[0] = fdbk->isAck[0];/*PCell*/
2794 isAck[1] = fdbk->isAck[0];/*PCell*/
2798 case RG_SCH_A_VAL_3:
2800 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2803 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
2804 hqP->hqE->cell->cellId,
2807 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
2809 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
2811 { /* Sec cell is in mimo mode */
2812 /* use 0 and 1 for sec in case of pucch
2813 * and 1 and 2 in case of PUSCH as the primary cell is in
2814 * siso case as A =3 */
2817 isAck[0] = fdbk->isAck[0];
2818 isAck[1] = fdbk->isAck[1];
2820 {/* PUSCH as per 36.212 serction 5.2.26*/
2821 isAck[0] = fdbk->isAck[1];
2822 isAck[1] = fdbk->isAck[2];
2825 {/* sec cell is in siso */
2826 isAck[0] = fdbk->isAck[2];
2830 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2831 {/* primay cell is in mimo
2833 isAck[0] = fdbk->isAck[0];
2834 isAck[1] = fdbk->isAck[1];
2839 isAck[0] = fdbk->isAck[2];
2841 {/* PUSCH as per 36.212 serction 5.2.26*/
2842 isAck[0] = fdbk->isAck[0];
2848 case RG_SCH_A_VAL_4:
2850 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2852 isAck[0] = fdbk->isAck[2];
2853 isAck[1] = fdbk->isAck[3];
2856 if(isAck[0] == TFU_HQFDB_ACK)
2858 gSCellTb1AckCount++;
2859 }else if(isAck[0] == TFU_HQFDB_NACK)
2861 gSCellTb1NackCount++;
2864 gSCellTb1DtxCount++;
2867 if(isAck[1] == TFU_HQFDB_ACK)
2869 gSCellTb2AckCount++;
2870 }else if(isAck[1] == TFU_HQFDB_NACK)
2872 gSCellTb2NackCount++;
2875 gSCellTb2DtxCount++;
2883 isAck[0] = fdbk->isAck[0];
2884 isAck[1] = fdbk->isAck[1];
2887 if(isAck[0] == TFU_HQFDB_ACK)
2889 gPCellTb1AckCount++;
2890 }else if(isAck[0] == TFU_HQFDB_NACK)
2892 gPCellTb1NackCount++;
2895 gPCellTb1DtxCount++;
2898 if(isAck[1] == TFU_HQFDB_ACK)
2900 gPCellTb2AckCount++;
2901 }else if(isAck[1] == TFU_HQFDB_NACK)
2903 gPCellTb2NackCount++;
2906 gPCellTb2DtxCount++;
2921 }/* End of rgSchGetHqFdbkPos */
2923 Void rgSchGetHqFdbkPosFormat3
2925 RgSchDlHqProcCb *hqP,
2930 uint8_t cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
2931 isAck[0] = (uint8_t)fdbk[cellIdx];
2932 isAck[1] = (uint8_t)fdbk[cellIdx + 1];
2935 /** * @brief Handler for HARQ feedback received for DL transmission.
2939 * Function : rgSCHDhm5gtfHqFdbkInd
2941 * This function shall act on the feedback received from TOM for DL
2942 * transmission. If the feedback for msg4 is final (after max transmissions
2943 * or ACK) inform RAM that Msg4 transmission is done.
2946 * @param[in] Void *cb
2947 * @param[in] uint8_t cbType
2948 * @param[in] RgSchCellCb *cell
2949 * @param[in] RgTfuHarqAckIndInfo *fdbk
2950 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2951 * @param[in] RgSchErrInfo *err
2956 S16 rgSCHDhm5gtfHqFdbkInd
2960 CmLteTimingInfo timingInfo,
2965 RgSchDlHqProcCb *hqP = NULLP;
2966 CmLList *node = NULLP;
2970 Bool isMsg4 = FALSE;
2973 uint8_t hqPCount = 0;
2974 RgInfRlsHqInfo *rlsHqBufs = NULLP;
2976 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
2978 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
2980 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
2982 hqPCount = lnk->count;
2987 hqP = (RgSchDlHqProcCb *)node->node;
2989 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
2990 procId = hqP->procId;
2992 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2994 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
2996 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
2997 timingInfo, fdbk, rlsHqBufs, err);
2999 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3001 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3002 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3004 rlsHqBufs->numUes++;
3010 } /* rgSCHDhm5gtfHqFdbkInd */
3012 /** * @brief Handler for HARQ feedback received for DL transmission.
3016 * Function : rgSCHDhmHqFdbkInd
3018 * This function shall act on the feedback received from TOM for DL
3019 * transmission. If the feedback for msg4 is final (after max transmissions
3020 * or ACK) inform RAM that Msg4 transmission is done.
3023 * @param[in] Void *cb
3024 * @param[in] uint8_t cbType
3025 * @param[in] RgSchCellCb *cell
3026 * @param[in] RgTfuHarqAckIndInfo *fdbk
3027 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3028 * @param[in] RgSchErrInfo *err
3033 S16 rgSCHDhmHqFdbkInd
3038 CmLteTimingInfo timingInfo,
3040 RgInfRlsHqInfo *rlsHqBufs,
3044 RgSchDlHqTbCb *tbCb;
3045 RgSchDlHqEnt *hqE = NULLP;
3046 RgSchDlHqProcCb *hqP = NULLP;
3047 CmLList *node = NULLP;
3049 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3050 RgSchUeCb *ue = NULLP;
3054 Bool isMsg4 = FALSE;
3055 RgSchRaCb *raCb = NULLP;
3057 /* Added Insure Fixes Of UR.Initialized procId */
3059 /* DTX Change: Bool is converted into uint8_t*/
3060 uint8_t isAck[2]={0}; /*Changed to Array of 2*/
3062 uint8_t hqPCount = 0;
3065 CmLteTimingInfo fdbkRcptTime = timingInfo;
3066 #ifdef RGSCH_SPS_STATS
3067 RgSchCmnDlHqProc *cmnHqDl;
3071 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3073 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3075 /* Get the subframe associated with the feedback */
3076 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3077 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3078 * serving the purpose */
3079 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3081 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3082 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3084 raCb = (RgSchRaCb *)(cb);
3086 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3092 rnti = raCb->tmpCrnti;
3096 ue = (RgSchUeCb *)(cb);
3097 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3099 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3102 hqPCount = lnk->count;
3105 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3110 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3111 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3112 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3113 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3114 from get CQI from cmInfo->cqi
3115 from cmInfo get iTbs cmInfo->iTbs[0]
3116 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3117 Update stats in cellCb
3118 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3119 if (fdbk->isAck == TRUE)
3120 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3122 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3123 DL Ack/Nack statistics
3125 #ifdef MAC_SCH_STATS
3126 if (hqE->ue != NULLP)
3128 RgSchUeCb *ueCb = hqE->ue;
3129 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3130 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3131 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3132 static uint32_t retxCnt = 0;
3134 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3136 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3141 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3143 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3144 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3146 #endif /* MAC_SCH_STATS */
3148 /* Fetch the harqProc from the inUse list */
3150 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3151 /* Call Common module with the feedback information */
3152 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3154 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3156 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3159 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3160 {/* Feedback for SPS Release on PCell
3161 If Pcell is in mimo, feedback index will be 0
3163 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3165 isAck[0] = fdbk->isAck[0];
3168 isAck[0] = fdbk->isAck[2];
3171 /* Not releasing pdcch here
3172 * as it is already done at the time of
3174 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3181 DU_LOG("\nERROR --> SCH : CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3182 "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3187 isAck[0] = fdbk->isAck[0];
3188 /* Note: Since relPdcchFbkTimimg matches with the recieved
3189 * feedback, assumed that feedback is for release PDCCH */
3190 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3192 /* Remove release PDCCH from the subframe */
3193 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3194 sf->relPdcch = NULLP;
3199 #endif /* LTEMAC_SPS */
3201 /* Remove the harq process from the subframe */
3202 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3203 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3216 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3218 hqP = (RgSchDlHqProcCb *)node->node;
3220 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3222 procId = hqP->procId;
3224 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3226 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3227 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3229 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3231 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3236 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3238 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3240 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3242 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3243 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3246 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3248 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3249 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3251 rlsHqBufs->numUes++;
3256 node = sf->ackNakRepQ.first;
3259 tbCb = (RgSchDlHqTbCb *)(node->node);
3262 procId = hqP->procId;
3263 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3264 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3265 if (HQ_TB_WAITING == tbCb->state)
3267 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3268 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3269 timingInfo, isAck[0], rlsHqBufs, err);
3271 hqP->cwSwpEnabled = FALSE;
3272 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3274 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3275 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3277 rlsHqBufs->numUes++;
3284 } /* rgSCHDhmHqFdbkInd */
3285 #endif /* LTE_FDD */
3289 * @brief Handler for Harq related UE configuration.
3293 * Function : rgSCHDhmRgrUeCfg
3295 * This function shall fetch the harq related information into the
3296 * respective ueCb from the UE configuration as provided by the
3299 * @param[in] RgSchCellCb *cell
3300 * @param[in] RgSchUeCb *ueCb
3301 * @param[in] RgrUeCfg *ueCfg
3302 * @param[out] RgSchErrInfo *err
3307 Void rgSCHDhmRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ueCb,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3312 /* Initialize the TA Timer */
3313 cmInitTimers(&ueCb->taTmr, 1);
3315 /* Setting these values irrespective of taTmr value */
3316 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3317 /* Corrected default value of TA as per 36.213, 4.2.3 */
3318 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3320 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3321 ueCb->dl.taCb.outStndngTa = FALSE;
3322 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3324 /* Start TA timer only if cfgd as FINITE value */
3325 if (ueCfg->ueTaTmrCfg.pres)
3327 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3328 * TA command before the expiry of TA at UE. Also considering for
3329 * possible retx for this TA command */
3330 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3331 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3333 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3335 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3338 } /* rgSCHDhmRgrUeCfg */
3342 * @brief Handler for HARQ related UE Reconfiguration
3346 * Function : rgSCHDhmRgrCellCfg
3348 * This function shall fetch the HARQ related information into the
3349 * respective ueCb from the UE configuration as provided by the
3352 * @param[in] RgSchCellCb *cell
3353 * @param[in] RgrCellCfg *cellCfg
3354 * @param[out] RgSchErrInfo *err
3360 Void rgSCHDhmRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3363 PTR pUeCb;/* previous UE Control block */
3364 PTR nUeCb;/* next UE control block */
3372 cell->dlHqCfg = cellCfg->dlHqCfg;
3375 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3383 /* Update the DL Harq related information */
3384 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3385 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3388 /* Initializing the list for ueCbs that would have ta */
3389 cmLListInit(&cell->taUeLst);
3391 cmLListInit(&cell->ccchSduUeLst);
3392 cmLListInit(&cell->contResGrdTmrLst);
3393 cmLListInit(&cell->contResTmrLst);
3395 if(cell->emtcEnable)
3397 rgSCHDhmEmtcRgrCellCfg(cell);
3402 /* Initializing the timer queue */
3403 cell->tqCp.nxtEnt = 0;
3404 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3406 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3408 cell->tq[idx].first = NULLP;
3409 cell->tq[idx].tail = NULLP;
3412 } /* rgSCHDhmRgrCellCfg */
3415 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3419 * Function : rgSCHDhmRgrCellRecfg
3421 * This function shall fetch the HARQ related information into the
3422 * respective ueCb from the UE configuration as provided by the
3425 * @param[in] RgSchCellCb *cell
3426 * @param[in] RgrCellRecfg *cellRecfg
3427 * @param[out] RgSchErrInfo *err
3433 Void rgSCHDhmRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *cellRecfg,RgSchErrInfo *err)
3436 PTR pUeCb;/* previous UE Control block */
3437 PTR nUeCb;/* next UE control block */
3444 /* Update the cell with recieved configuration */
3445 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3447 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3451 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3459 /* Update the DL Harq related information */
3460 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3461 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3466 } /* rgSCHDhmRgrCellRecfg */
3469 * @brief Handler for freeing up the HARQ related information from ueCb
3473 * Function : rgSCHDhmFreeUe
3475 * This function shall free up the HARQ specific information from ueCb.
3477 * @param[in] RgSchUeCb *ueCb
3482 Void rgSCHDhmFreeUe(RgSchUeCb *ueCb)
3485 /* If TA Timer is running. Stop it */
3486 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3488 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3491 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3492 * doesn't expire after UE is deleted */
3494 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3496 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3498 #endif /* ifdef RGR_V1*/
3501 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3503 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3506 /* This UE needs to be removed from its entry into cell's taUeLst */
3507 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3508 if(ueCb->taLnk.node)
3510 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3511 ueCb->taLnk.node = NULLP;
3514 if (ueCb->dlTaLnk.node != NULLP)
3516 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3517 * function directly from other modules. APIs should be defined and/or used
3518 * instead. Please check for other possible incorrect usage. */
3519 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3524 } /* rgSCHDhmFreeUe */
3527 * @brief Handler for updating the TA.
3531 * Function : rgSCHDhmUpdTa
3533 * This function shall update the TA received.
3535 * @param[in] RgSchCellCb *cell
3536 * @param[in] RgSchUeCb *ueCb
3537 * @param[in] uint8_t ta
3542 Void rgSCHDhmUpdTa(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t ta)
3545 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3547 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3548 ueCb->dl.taCb.numRemSf = 2;
3549 rgSCHUtlDlTARpt(cell, ueCb);
3550 /* If TA Timer is running. Stop it */
3551 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3553 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3556 /* SR_RACH_STATS : TA MODIFIED */
3557 if (ueCb->dl.taCb.ta != ta)
3561 ueCb->dl.taCb.ta = ta;
3565 /* [ccpu00121813]-ADD-Updating outstanding values
3566 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3567 * has been scheduled,further TA values get stored in outstndngTaval.
3568 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3569 * then schedule the outstanding TA val if present */
3570 ueCb->dl.taCb.outStndngTa = TRUE;
3571 ueCb->dl.taCb.outStndngTaval = ta;
3575 } /* rgSCHDhmUpdTa */
3577 /** @brief This function handles the TA timer expiry.
3581 * Function: This function handled the TA Expiry.
3587 * @param[in] RgSchUeCb *ueCb
3592 Void rgSCHDhmProcTAExp( RgSchUeCb *ueCb)
3594 /* Ask scheduler to schedule this UE */
3595 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3596 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
3598 } /* end of rgSCHDhmProcTAExp */
3600 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
3602 * @brief Handler for Adding scheduled logical channel data information
3607 * Function : rgSCHDhmAddLcData
3609 * This function shall add the scheduled logical channel data
3610 * information to the HARQ process.
3612 * @param[in] RgSchLchAllocInfo *lchData
3613 * @param[in] RgSchDlHqTbCb *tbInfo
3618 S16 rgSCHDhmAddLcData(Inst inst,RgSchLchAllocInfo *lchData,RgSchDlHqTbCb *tbInfo)
3621 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
3626 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
3632 } /* rgSCHDhmAddLcData */
3636 * @brief Handler for releaseing the subframe allocation.
3640 * Function : rgSCHDhmTddRlsSubFrm
3642 * This function shall be invoked to release the DL Sf
3643 * allocations for which HARQ feedback time has expired.
3645 * @param[in] RgSchCellCb *cellCb
3646 * @param[in] CmLteTimingInfo uciTimingInfo;
3651 S16 rgSCHDhmTddRlsSubFrm(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3653 CmLteTimingInfo dlSfTime;
3654 RgSchTddDlAscSetIdxK ascIdx;
3659 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3660 noFdbks = ascIdx.numFdbkSubfrms;
3661 for(i=0; i < noFdbks; i++)
3663 /* Get the subframe and sfn for which HARQ Ack/Nack
3665 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3666 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3667 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3668 * as it is serving the purpose */
3669 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3670 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
3673 }/* rgSCHDhmTddRlsSubFrm */
3676 uint32_t macDtx = 0;
3679 * @brief Handler for Removing the HARQ process from a dlsf.
3683 * Function : rgSCHDhmRlsDlsfHqProc
3685 * This function shall be invoked for every tti. It goes back to
3686 * to the sixth last subframe to check whether it still exists. If
3687 * that exists this function traverses through the entire harq
3688 * proc list associated and frees up all of them.
3690 * @param[in] RgSchCellCb *cellCb
3691 * @param[in] CmLteTimingInfo timingInfo
3696 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3699 CmLteTimingInfo dlSfTime;
3700 CmLteTimingInfo nxtfrm = {0,0};
3701 RgSchDlHqProcCb *tmpHqProc;
3702 RgSchTddDlAscSetIdxK ascIdx;
3705 RgSchDlSf *nxtDlsf = NULLP;
3709 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
3710 uint8_t maxRetx=FALSE;
3711 RgSchTddANInfo *anInfo = NULLP;
3712 RgSchDlHqTbCb *tbCb;
3713 RgSchUeCb *ue = NULLP;
3716 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3717 noFdbks = ascIdx.numFdbkSubfrms;
3718 for(i=0; i < noFdbks; i++)
3720 /* Get the subframe and sfn for which HARQ Ack/Nack
3722 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3723 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3724 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3725 * as it is serving the purpose */
3726 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3728 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
3729 if(cellCb->ulDlCfgIdx != 5)
3731 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
3733 /* Subframe is present. Delete all the harq associations from
3737 /*Handling for Msg4*/
3738 node = dlSf->msg4HqPLst.first;
3741 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
3743 tmpHqProc->cwSwpEnabled = FALSE;
3744 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
3746 tbCb = &tmpHqProc->tbInfo[0];
3748 /* Fix : syed MultiUe per TTI crash in TA List. */
3752 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3755 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3757 /* Delete the Harq Association. Release the Harq Process */
3758 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3760 if (tbCb->taSnt == TRUE)
3762 /* [ccpu00127148] Correcting the check */
3763 if (TRUE == maxRetx)
3765 tbCb->taSnt = FALSE;
3766 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3767 ue->dl.taCb.state = RGSCH_TA_IDLE;
3769 rgSCHUtlReTxTa(cellCb, ue);
3775 node = dlSf->ueLst.first;
3781 ue = (RgSchUeCb *)(node->node);
3785 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
3788 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
3789 hqPNode = hqPNode->next;
3790 for (idx = 0 ;idx < 2; idx++)
3792 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
3794 tbCb = &tmpHqProc->tbInfo[idx];
3796 /* Fix : syed MultiUe per TTI crash in TA List. */
3800 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3803 /* Update feedback time for this process so that
3804 * next subframe its picked up */
3806 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3807 tmpHqProc->hqE->cell->instIdx,
3808 tmpHqProc->hqE->cell->cellId,
3810 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3812 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
3816 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
3817 "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX"
3818 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
3819 uciTimingInfo.slot));
3821 else if (tbCb->fbkRepCntr == 0)
3823 /* Initialise the Ack/Nack feedback */
3825 if(!(anInfo->dlDai))
3827 rgSCHUtlInitUeANFdbkInfo(anInfo);
3832 /* Update feedback time for this process so that
3833 * * next subframe its picked up */
3834 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3835 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3836 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3837 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
3842 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3843 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
3846 /* Delete the Harq Association. Release the Harq Process */
3847 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3849 if (tbCb->taSnt == TRUE)
3851 /* [ccpu00127148] Correcting the check */
3852 if (TRUE == maxRetx)
3854 tbCb->taSnt = FALSE;
3855 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3856 ue->dl.taCb.state = RGSCH_TA_IDLE;
3858 rgSCHUtlReTxTa(cellCb, ue);
3860 DU_LOG("\nDEBUG --> SCH : Nack/DTX Rcvd for TA. Max Tries Attempted");
3869 node = dlSf->ackNakRepQ.first;
3872 tbCb = (RgSchDlHqTbCb *)(node->node);
3873 tmpHqProc = tbCb->hqP;
3874 /* [ccpu00121813]-ADD-Fetch ueCb */
3875 ue = tmpHqProc->hqE->ue;
3876 /* Fix : syed MultiUe per TTI crash in TA List. */
3881 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
3882 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
3886 /* If This is not the last repetition */
3887 if (tbCb->fbkRepCntr > 1)
3889 /* Update feedback time for this process so that
3890 * next subframe its picked up */
3892 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3893 tmpHqProc->hqE->cell->instIdx,
3894 tmpHqProc->hqE->cell->cellId,
3896 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3898 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
3904 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3905 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3906 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3907 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3913 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3915 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
3917 /*even if one NACK, we consider the feedback
3918 * on a whole as NACk */
3919 if ( tbCb->nackCount != 0 )
3921 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
3925 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3929 /* Delete the Harq Association. Release the Harq Process */
3930 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3932 }/*if(((tbCb->nackCount+....*/
3935 if (tbCb->taSnt == TRUE)
3937 /* [ccpu00127148] Correcting the check */
3938 if (TRUE == maxRetx)
3940 tbCb->taSnt = FALSE;
3941 ue->dl.taCb.state = RGSCH_TA_IDLE;
3943 rgSCHUtlReTxTa(cellCb, ue);
3944 DU_LOG("\nDEBUG --> SCH : Nack/DTX Rcvd for TA. Max Tries Attempted");
3951 }/* rgSCHDhmRlsDlsfHqProc */
3952 #else /* ifdef LTE_TDD */
3954 * @brief Handler for Removing the HARQ process from a dlsf.
3958 * Function : rgSCHDhmRlsDlsfHqProc
3960 * This function shall be invoked for every tti. It goes back to
3961 * to the sixth last subframe to check whether it still exists. If
3962 * that exists this function traverses through the entire harq
3963 * proc list associated and frees up all of them.
3965 * @param[in] RgSchCellCb *cell
3970 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cell,CmLteTimingInfo timingInfo)
3973 CmLteTimingInfo frm;
3974 RgSchDlHqProcCb *tmpHqProc;
3979 RgSchDlHqTbCb *tbCb;
3982 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
3983 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3984 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3985 * as it is serving the purpose */
3986 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
3989 /* Get the required Last subframe */
3990 sf = rgSCHUtlSubFrmGet(cell, frm);
3993 /*Handling for Msg4*/
3994 node = sf->msg4HqPLst.first;
3997 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
3998 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4000 tbCb = &tmpHqProc->tbInfo[0];
4001 /* Fix : syed MultiUe per TTI crash in TA List. */
4004 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4005 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4008 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4009 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4011 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4016 if (tbCb->fbkRepCntr != 0)
4018 /* Update timingInfo for this hqP so that next subframe its picked up */
4019 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4020 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4024 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4026 /* Delete the Harq Association. Release the Harq Process */
4027 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4031 /* Subframe is present. Delete all the harq associations from
4034 node = sf->ueLst.first;
4037 ue = (RgSchUeCb *)(node->node);
4041 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4045 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4046 tmpHqProc->cwSwpEnabled = FALSE;
4047 hqPNode = hqPNode->next;
4048 for (idx = 0 ;idx < 2; idx++)
4050 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4052 tbCb = &tmpHqProc->tbInfo[idx];
4053 /* Fix : syed MultiUe per TTI crash in TA List. */
4056 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4057 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4060 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4061 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4063 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4068 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4071 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4074 /* Delete the Harq Association. Release the Harq Process */
4075 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4077 if (tbCb->taSnt == TRUE)
4079 /* [ccpu00127148] Correcting the check */
4080 if (TRUE == maxRetx)
4082 tbCb->taSnt = FALSE;
4083 ue->dl.taCb.state = RGSCH_TA_IDLE;
4085 rgSCHUtlReTxTa(cell, ue);
4086 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4087 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4090 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4091 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4100 } /* rgSCHDhmRlsDlsfHqProc */
4105 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4110 * Function: rgSCHDhmMarkSpsHqProc
4111 * Purpose: This function returns the HARQ process with the given ID.
4112 * Invoked by: SPS Module
4114 * - Get the HARQ process by index from the UE
4115 * - Set isSpsHqProc = TRUE
4117 * @param[in] RgSchUeCb *ue
4118 * @param[in] uint8_t idx
4120 * -# ROK if successful
4121 * -# RFAILED otherwise
4124 S16 rgSCHDhmMarkSpsHqProc(RgSchUeCb *ue,uint8_t idx)
4126 RgSchDlHqProcCb *hqP;
4128 /* Pick the proc based on the index provided */
4129 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4132 } /* rgSCHDhmMarkSpsHqProc */
4133 #endif /* RG_UNUSED */
4134 #endif /* LTEMAC_SPS */
4137 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4141 * Function : rgSCHDhmProcHqFdbkAckNackRep
4143 * This function shall act on the feedback received from TOM for DL
4147 * @param[in] RgSchDlHqProcCb *hqP
4148 * @param[in] RgSchDlSf *sf
4149 * @param[in] uint8_t tbCnt
4150 * @param[in] uint8_t *isAck
4155 static S16 rgSCHDhmProcHqFdbkAckNackRep(RgSchDlHqProcCb *hqP,RgSchDlSf *sf,uint8_t tbCnt,uint8_t *isAck)
4157 /* Check if this is repeating UE */
4158 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4159 /* Check if last repetition */
4160 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4162 /* Update timingInfo for this hqP so that next subframe its picked up */
4163 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4164 hqP->tbInfo[tbCnt].timingInfo, 1);
4168 /* Take decision here based on the number
4169 * of DTX's,NACK's and ACK's received
4171 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4172 (hqP->tbInfo[tbCnt].dtxCount)))
4174 *isAck = TFU_HQFDB_ACK;
4176 /*even a single NACK indicates that UE received
4179 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4181 *isAck = TFU_HQFDB_NACK;
4185 *isAck = TFU_HQFDB_DTX;
4189 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4192 #endif /* ifndef LTE_TDD */
4195 /* Freeing up the HARQ proc blocked for
4196 * indefinite time in case of Retx */
4198 * @brief This function handles the scenario in case Retx allocation is failed.
4202 * Function: rgSCHDhmDlRetxAllocFail
4205 * @param[in] RgSchUeCb *ue
4206 * @param[in] RgSchDlHqProcCb *hqP
4210 S16 rgSCHDhmDlRetxAllocFail(RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
4213 RgInfRlsHqInfo *rlsHqInfo;
4215 Bool maxRetx = FALSE;
4216 RgSchCmnCell *cellSch;
4218 cell = hqP->hqE->cell;
4219 cellSch = RG_SCH_CMN_GET_CELL(cell);
4220 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4222 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4223 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4225 hqP->tbInfo[0].cntrRetxAllocFail++;
4228 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4229 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4231 hqP->tbInfo[1].cntrRetxAllocFail++;
4234 /* initialize MAC-SCH interface HARQ release info */
4235 rlsHqInfo->numUes = 0;
4236 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4238 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4239 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4241 if (hqP->hqE->msg4Proc == hqP)
4243 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4247 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4250 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4255 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4256 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4260 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4261 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4264 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4265 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4268 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4269 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4270 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4273 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4274 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4276 if (hqP->hqE->msg4Proc == hqP)
4278 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4282 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4285 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4287 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4288 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4289 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4290 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4291 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4294 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4296 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4297 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4299 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4302 /* send HARQ release to MAC */
4303 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4305 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4306 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4307 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4308 rlsHqInfo->numUes = 1;
4310 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4311 RgSchMacRlsHq(&pst, rlsHqInfo);
4318 static S16 rgSCHDhmUpdateAckNackHistory(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t hqfdbk,uint8_t tbCnt)
4322 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4325 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4328 if (hqfdbk == TFU_HQFDB_ACK)
4330 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4334 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4337 printf("\nDEBUG --> SCH: deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4338 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4339 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4342 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4347 S16 rgSCHDhmUpdBlerBasediTbsEff(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t tbCnt)
4351 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4352 uint8_t cfi = cellSch->dl.currCfi;
4353 uint8_t maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4354 maxiTbs = RG_SCH_DL_MAX_ITBS;
4356 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4357 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4361 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4362 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4366 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4367 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4371 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4372 ueDl->laCb[tbCnt].deltaiTbs)/100),
4373 ueCb->cell->thresholds.maxDlItbs);
4376 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4378 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4380 /* Eff for CW for 1 Layer Tx */
4381 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4382 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4383 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4385 /* Eff for CW for 2 Layer Tx */
4386 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4387 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4388 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4396 * @brief This function Processes the Hq Fdbk in case of
4397 * special Bundling in TDD (FAPIv1.1: Table 79)
4401 * Function: rgSCHDhmPrcSplBundlFdbk
4402 * Purpose: To Interpret the Harq Feedback according to
4403 * table 7.3-1: 36.213
4405 * 0 = 0 or None (UE detect at least one DL is missed)
4406 * 1 = 1 or 4 or 7 ACKs reported
4407 * 2 = 2 or 5 or 8 ACKs reported
4408 * 3 = 3 or 6 or 9 ACKs reported
4409 * 4 = DTX (UE did not transmit anything)
4411 * @param[in] TfuHqInfo *fdbk
4412 * @param[in] uint8_t hqCnt
4416 static Void rgSCHDhmPrcSplBundlFdbk(RgSchCellCb *cell,TfuHqInfo *fdbk,uint8_t hqCnt)
4420 /* Num of ACKs reported by UE */
4421 numOfAcks = fdbk->isAck[0];
4423 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4424 fdbk->isAck[0] == TFU_HQFDB_DTX)
4430 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4431 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4433 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4436 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4437 the PDSCH trasnmission (spatial bundling). So we have
4438 to assume same feedback for both codewords */
4440 for(uint8_t idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4442 fdbk->isAck[idx] = fdbk->isAck[0];
4445 fdbk->isAck[1] = fdbk->isAck[0];
4453 * @brief This function adds HARQ process to FREE list
4457 * Function: rgSCHDhmHqPAdd2FreeLst
4460 * Invoked by: scheduler
4462 * @param[out] RgDlHqProc *hqP
4466 Void rgSCHDhmHqPAdd2FreeLst(RgSchDlHqProcCb *hqP)
4473 printf("\nDEBUG --> SCH: Crashing already part of free lst\n");
4474 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4478 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
4479 hqP->hqPLst = &hqP->hqE->free;
4483 if (hqP->hqE->free.count > 8)
4486 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4487 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4493 rgSCHLaaHndlHqProcFree(hqP);
4497 } /* rgSCHDhmHqPAdd2FreeLst */
4501 * @brief This function adds HARQ process to inUse list
4505 * Function: rgSCHDhmHqPAdd2InUseLst
4508 * Invoked by: scheduler
4510 * @param[out] RgDlHqProc *hqP
4514 Void rgSCHDhmHqPAdd2InUseLst(RgSchDlHqProcCb *hqP)
4521 printf("\nDEBUG --> SCH: Crashing already part of inuse lst\n");
4522 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4526 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
4527 hqP->hqPLst = &hqP->hqE->inUse;
4531 if (hqP->hqE->inUse.count > 8)
4534 printf("\nDEBUG --> SCH: Crashing invalid hq count \n");
4535 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4541 } /* rgSCHDhmHqPAdd2InUseLst */
4544 * @brief This function adds HARQ process to FREE list
4548 * Function: rgSCHDhmHqPDelFrmFreeLst
4551 * Invoked by: scheduler
4553 * @param[out] RgDlHqProc *hqP
4557 Void rgSCHDhmHqPDelFrmFreeLst(RgSchDlHqProcCb *hqP)
4564 printf("\nDEBUG --> SCH: Crashing not part of any lst\n");
4565 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4570 if (hqP->hqPLst != &hqP->hqE->free)
4573 printf("\nDEBUG --> SCH: Crashing del from wrong lst\n");
4574 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4579 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
4580 hqP->hqPLst = NULLP;
4583 if (hqP->hqE->free.count > 8)
4586 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4587 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4593 } /* rgSCHDhmHqPDelFrmFreeLst */
4598 * @brief This function adds HARQ process to FREE list
4602 * Function: rgSCHDhmHqPDelFrmInUseLst
4605 * Invoked by: scheduler
4607 * @param[out] RgDlHqProc *hqP
4611 Void rgSCHDhmHqPDelFrmInUseLst(RgSchDlHqProcCb *hqP)
4618 printf("\nDEBUG --> SCH: Crashing not part of any lst\n");
4619 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4625 if (hqP->hqPLst != &hqP->hqE->inUse)
4628 printf("\nDEBUG --> SCH: Crashing del from wrong lst\n");
4629 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4634 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
4635 hqP->hqPLst = NULLP;
4638 if (hqP->hqE->inUse.count > 8)
4641 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4642 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4648 } /* rgSCHDhmHqPDelFrmInUseLst */
4651 /**********************************************************************
4654 **********************************************************************/