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"
47 #include "rl_interface.h"
48 #include "rl_common.h"
50 /* header/extern include files (.x) */
55 #include "rg_sch_inf.x" /* typedefs for Scheduler */
57 #include "rg_sch_cmn.x"
59 #ifdef RGSCH_SPS_STATS
60 uint32_t rgNumSPSSchedDropMaxRetx;
68 RgSchNackAckStats hqFailStats;
69 RgSchHqRetxStats hqRetxStats;
70 #endif /* MAC_SCH_STATS */
71 //Chandan Stats Collection
74 RgSchDlHqStats dlHqStats[10000] = {{0,0,0}};
78 /* For special bundling case: convert numOfAcks to ACK/NACK
79 * The below table derives the HARQ aknowledgement as ACK or NACK using the
80 * number of transmission done and the feedback value received
81 * The below table is based on Table 7.3-X from 36.213 and
82 * table 79 from FAPIv1.1 doc
84 uint8_t rgSchNumOfAcksToAckNack[RG_SCH_MAX_NUM_EXPECTED_ACKS][RG_SCH_NUM_FDBK_VALUE] = {
85 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
86 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
87 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
88 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
89 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
90 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
91 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
92 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
93 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK}
101 static Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, uint8_t tbIdx, uint8_t fdbk,
102 Bool maxHqRetxReached));
103 void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
105 static S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
106 RgSchDlHqProcCb *hqP,
113 static S16 rgSCHDhmUpdateAckNackHistory ARGS((
121 static Void rgSCHDhmPrcSplBundlFdbk ARGS((
127 static Void rgSchGetHqFdbkPosForM1 ARGS((
129 RgSchDlHqProcCb *hqP,
133 RgSchTddANInfo *anInfo
135 static Void rgSchGetHqFdbkPosForM234 ARGS((
137 RgSchDlHqProcCb *hqP,
141 RgSchTddANInfo *anInfo,
143 CmLteTimingInfo timeInfo
148 /* Freeing up the HARQ proc blocked for
149 * indefinite time in case of Retx */
150 S16 rgSCHDhmDlRetxAllocFail ARGS((
152 RgSchDlHqProcCb *proc
156 S16 rgSCHDhmEmtcRgrCellCfg ARGS((
162 uint32_t gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
163 uint32_t gSCellSchedCount,gPrimarySchedCount;
164 uint32_t gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
165 uint32_t gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
166 uint32_t gHqFdbkCount;
170 Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
172 RgSchEmtcDlSf *subFrm,
173 RgSchDlHqProcCb *hqP,
177 RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
182 Void rgSCHEmtcHqInfoAlloc ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP));
184 /* forward references */
187 * @brief This function initializes the DL HARQ Entity of UE.
191 * Function: rgSCHDhmHqEntInit
192 * Purpose: This function initializes the DL HARQ entity of
193 * UE control block. This is performed at the time
194 * of creating UE control block.
196 * Invoked by: configuration module
198 * @param[in] RgSchCellCb* cell
199 * @return RgSchDlHqEnt *
202 /*MS_WORKAROUND for ccpu00122893*/
203 Void rgSCHDhmHqEntReset(RgSchDlHqEnt *hqE)
205 RgSchDlHqProcCb *hqP;
207 cmLListInit(&hqE->inUse);
208 cmLListInit(&hqE->free);
209 for (i=0; i < hqE->numHqPrcs; i++)
211 hqP = &hqE->procs[i];
214 /* Fix - reset numLch */
215 hqP->tbInfo[0].numLch = 0;
216 hqP->tbInfo[1].numLch = 0;
217 hqP->tbInfo[0].txCntr = 0;
218 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
219 hqP->tbInfo[1].txCntr = 0;
220 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
221 hqP->tbInfo[0].tbIdx = 0;
222 hqP->tbInfo[1].tbIdx = 1;
223 hqP->tbInfo[0].hqP = hqP;
224 hqP->tbInfo[1].hqP = hqP;
225 hqP->tbInfo[0].state = HQ_TB_ACKED;
226 hqP->tbInfo[1].state = HQ_TB_ACKED;
227 hqP->tbInfo[0].contResCe = NOTPRSNT;
228 hqP->tbInfo[1].contResCe = NOTPRSNT;
229 hqP->lnk.node = (PTR)hqP;
230 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
232 rgSCHDhmHqPAdd2FreeLst(hqP);
233 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
234 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
235 hqP->drxCb.rttIndx = DRX_INVALID;
236 hqP->drxCb.reTxIndx = DRX_INVALID;
237 hqP->tbInfo[0].cntrRetxAllocFail = 0;
238 hqP->tbInfo[1].cntrRetxAllocFail = 0;
239 hqP->hasDcch = FALSE;
240 hqP->cwSwpEnabled = FALSE;
245 rgSCHLaaResetDlHqProcCb(hqP);
249 } /* rgSCHDhmHqEntReset */
252 * @brief This function assigns dlHqEnt of raCb to ueCb.
256 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
257 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
259 * Invoked by: configuration module
261 * @param[in] RgSchUeCb *ue
262 * @param[in] RgSchRaCb *raCb
266 Void rgSCHDhmAssgnUeHqEntFrmRaCb(RgSchUeCb *ue,RgSchRaCb *raCb)
269 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
270 ue->cellInfo[0]->hqEnt->ue = ue;
271 /* Update the DL Harq related information */
272 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
274 /* Fix : set UE active in DL as UE initialization completed */
275 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
276 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
277 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
283 * @brief This function deletes the dlHqEnt.
287 * Function: rgSCHDhmDelHqEnt
288 * Purpose: This function deletes the dlHqEnt.
290 * Invoked by: configuration module
292 * @param[in] RgSchCellCb *cell
293 * @param[in] RgSchDlHqEnt **hqE
297 Void rgSCHDhmDelHqEnt(RgSchCellCb *cell,RgSchDlHqEnt **hqE)
305 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
307 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
308 sizeof(RgSchDlHqEnt));
313 RgSchDlHqEnt *rgSCHDhmHqEntInit(RgSchCellCb *cell)
316 Inst inst = cell->instIdx;
318 /* Init the HARQ data structure */
319 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
321 DU_LOG("\nERROR --> SCH: rgSCHDhmHqEntInit hqE alloc fail");
325 /* Init the HARQ processes */
326 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
327 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
328 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
330 DU_LOG("\nERROR --> SCH: rgSCHDhmHqEntInit hqP alloc fail in hqE");
334 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
338 rgSCHLaaInitDlHqProcCb (cell, hqE);
341 /* Initialize maximum tranmission counter */
342 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
345 /* MW_WORKAROUND for ccpu00122893 */
346 rgSCHDhmHqEntReset(hqE);
352 } /* rgSCHDhmHqEntInit */
355 * @brief This function gets an available HARQ process.
359 * Function: rgSCHDhmGetAvlHqProc
360 * Purpose: This function returns an available HARQ process in
361 * the DL direction. All HARQ processes are maintained
362 * in queues of free and inuse.
364 * 1. Check if the free queue is empty. If yes, return
366 * 2. If not empty, update the proc variable with the
367 * first process in the queue. Return ROK.
369 * Invoked by: scheduler
371 * @param[in] RgSchUeCb *ue
372 * @param[in] CmLteTimingInfo timingInfo
373 * @param[out] RgSchDlHqProc **hqP
375 * -#ROK if successful
376 * -#RFAILED otherwise
379 S16 rgSCHDhmGetAvlHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo,RgSchDlHqProcCb **hqP)
381 RgSchDlHqEnt *hqE = NULLP;
382 RgSchDlHqProcCb *tmpHqProc;
385 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
389 DU_LOG("\nERROR --> SCH : rgSCHDhmGetAvlHqProc hqE NULL ue %d"
395 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
399 DU_LOG("\nERROR --> SCH : rgSCHDhmGetAvlHqProc free %d inUse %d ue %d"
400 , hqE->free.count, hqE->inUse.count, ue->ueId);
401 /* No Harq Process available in the free queue. */
405 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
408 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
410 if (ue->dl.isSpsHqPInUse)
412 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
414 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
419 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
423 /* No Harq Process available in the free queue. */
430 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
431 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
432 tmpHqProc->hasDcch = FALSE;
433 tmpHqProc->cwSwpEnabled = FALSE;
435 /* Remove the element from the free Queue */
436 //cmLListDelFrm(&hqE->free, tmp);
437 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
439 /* Add the element into the inUse Queue as well */
440 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
441 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
446 rgSCHLaaResetDlHqProcCb(tmpHqProc);
450 tmpHqProc->tbSizeAtEstimate[0] = 0;
451 tmpHqProc->tbSizeAtEstimate[1] = 0;
452 tmpHqProc->tbSizeAtFnlz[0] = 0;
453 tmpHqProc->tbSizeAtFnlz[1] = 0;
454 tmpHqProc->tbSizeOfMvdTb[0] = 0;
455 tmpHqProc->tbSizeOfMvdTb[1] = 0;
456 tmpHqProc->itbsAtEstimate[0] = 0;
457 tmpHqProc->itbsAtEstimate[1] = 0;
458 tmpHqProc->prbAtEstimate = 0;
461 } /* rgSCHDhmGetAvlHqProc */
465 * @brief This function adds HARQ process for a given TB in to
466 * the inuse queue upon retx.
470 * Function: rgSCHDhmHqTbRetx
471 * Purpose: This function handles when a HARQ process is scheduled
472 * for retransmission. It adds the HARQ procss to inuse
474 * 1. Check if this HqP is already added to the inUse
475 * queue as part of this function call for other
476 * TB's retransmission.
477 * 2. If already present in inUse Q then do not add.
479 * Invoked by: scheduler
481 * @param[in] RgSchDlHqEnt *hqE
482 * @param[in] CmLteTimingInfo timingInfo
483 * @param[out] RgDlHqProc *hqP
484 * @param[in] uint8_t tbIdx
488 Void rgSCHDhmHqTbRetx(RgSchDlHqEnt *hqE,CmLteTimingInfo timingInfo,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
490 uint8_t othrTbIdx = tbIdx ^ 1;
492 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
494 if (hqE->msg4Proc == hqP)
498 /* fix for ccpu00118633 No Hq proc Avl end*/
500 /* Extra:check if Harq process is already linked to in-use
501 Queue by means of other TB handling. */
502 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
505 if (hqE->msg4Proc != hqP)
507 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
508 rgSCHDhmHqPAdd2InUseLst(hqP);
512 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
515 } /* rgSCHDhmHqTbRetx */
518 * @brief This function returns last scheduled HARQ process for
519 * a UE's HARQ entity.
523 * Function: rgSCHDhmLastSchedHqProc
524 * Purpose: This function returns the last (most recent)
525 * process in the inUse list, which corresponds
526 * to the last scheduled process. Returns NULLP
528 * The reason for introducing this is to have
529 * an ability to check if UE was scheduled
530 * in the current subframe (scheduling would
531 * have caused a proc to be added to the end
532 * of the list, and checking time (only subframe
533 * number probably works) would confirm this.
535 * Invoked by: scheduler
537 * @param[in] RgSchDlHqEnt *hqE
538 * @return RgSchDlHqProcCb *
541 RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(RgSchDlHqEnt *hqE)
543 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
544 * until RACH procedure is completed */
545 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
549 return ((RgSchDlHqProcCb *)hqE->inUse.last->node);
550 } /* rgSCHDhmLastSchedHqProc */
554 * @brief This function gets an available HARQ process for MSG 4.
558 * Function: rgSCHDhmGetCcchSduHqProc
559 * Purpose: This function returns an available HARQ process in
560 * the DL direction. All HARQ processes are maintained
561 * in queues of free and inuse.
563 * 1. Check if the free queue is empty. If yes, return
565 * 2. If not empty, update the proc variable with the
566 * first process in the queue. Return ROK.
568 * Invoked by: scheduler
570 * @param[in] RgSchRaCb *raCb
571 * @param[in] CmLteTimingInfo timingInfo
572 * @param[out] RgSchDlHqProcCb **hqP
574 * -#ROK if successful
575 * -#RFAILED otherwise
578 S16 rgSCHDhmGetCcchSduHqProc
581 CmLteTimingInfo timingInfo,
582 RgSchDlHqProcCb **hqP
585 RgSchDlHqProcCb *tmpHqProc;
589 hqE = ueCb->cellInfo[0]->hqEnt;
590 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
593 /* No Harq Process available in the free queue. */
597 /* Remove the element from the free Queue and */
598 /* set the MSG 4 HARQ proc pointer */
599 //cmLListDelFrm(&hqE->free, tmp);
601 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
603 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
605 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
606 /* Fix : syed minor code reorg */
608 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
610 hqE->ccchSduProc = tmpHqProc;
611 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
612 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
615 } /* rgSCHDhmGetCcchSduHqProc */
619 * @brief This function gets an available HARQ process for MSG 4.
623 * Function: rgSCHDhmGetMsg4HqProc
624 * Purpose: This function returns an available HARQ process in
625 * the DL direction. All HARQ processes are maintained
626 * in queues of free and inuse.
628 * 1. Check if the free queue is empty. If yes, return
630 * 2. If not empty, update the proc variable with the
631 * first process in the queue. Return ROK.
633 * Invoked by: scheduler
635 * @param[in] RgSchRaCb *raCb
636 * @param[in] CmLteTimingInfo timingInfo
637 * @param[out] RgDlHqProc **hqP
639 * -#ROK if successful
640 * -#RFAILED otherwise
643 S16 rgSCHDhmGetMsg4HqProc(RgSchRaCb *raCb,CmLteTimingInfo timingInfo)
645 RgSchDlHqProcCb *tmpHqProc;
650 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
653 /* No Harq Process available in the free queue. */
657 /* Remove the element from the free Queue and */
658 /* set the MSG 4 HARQ proc pointer */
659 //cmLListDelFrm(&hqE->free, tmp);
660 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
661 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
662 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
663 hqE->msg4Proc = tmpHqProc;
666 } /* rgSCHDhmGetMsg4HqProc */
669 * @brief This function releases a HARQ process.
673 * Function: rgSCHDhmRlsHqpTb
674 * Purpose: This function resets the TB specific fields
675 * Based on the other TBs state, this HqProcess
676 * is returned to the HqEnt.
678 * 1. Add the HARQ process to the free queue.
679 * Invoked by: scheduler and HARQ processing
681 * @param[in] RgDlHqProc *hqP
682 * @param[in] uint8_t tbIdx
683 * @param[in] Bool togNdi
687 Void rgSCHDhmRlsHqpTb(RgSchDlHqProcCb *hqP,uint8_t tbIdx,Bool togNdi)
690 uint8_t othrTbIdx = tbIdx ^ 1;
692 RgSchCmnDlHqProc *cmnHqDl;
696 RgSchDlLcCb* lcCb = NULLP;
700 /* Reset all tbInfo values */
705 if (hqP->hqE->ue != NULLP)
707 RgSchUeCb *ueCb = hqP->hqE->ue;
708 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
709 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
710 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
711 /* to get retransmission, decreasing transmission counter */
712 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
713 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
714 static uint32_t retxCnt1 = 0;
716 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
717 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
722 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
725 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
728 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
731 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
734 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
735 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
736 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
737 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
738 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
740 retxCnt1 += numDlRetx;
742 #endif /* MAC_SCH_STATS */
743 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
747 hqP->tbInfo[tbIdx].ndi ^= 1;
752 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
754 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
755 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
757 if (lcCb->lcType == CM_LTE_LCH_DTCH)
759 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
761 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
764 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
766 lcCb->qciCb->dlUeCount--;
774 hqP->tbInfo[tbIdx].tbSz = 0;
775 hqP->tbInfo[tbIdx].numLch = 0;
776 hqP->tbInfo[tbIdx].txCntr = 0;
777 /* FOR ACK NACK REP */
778 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
779 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
780 hqP->tbInfo[tbIdx].ackCount = 0;
781 /* pdcch is moved from TbCb to HqCb.
782 This pdcch will be set to NULL when
783 HqCb will be pushed to free list*/
784 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
785 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
786 hqP->tbInfo[tbIdx].nackCount = 0;
787 hqP->tbInfo[tbIdx].dtxCount = 0;
788 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
789 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
791 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
793 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
794 /* Handling msg4 hqProc */
795 if (hqE->msg4Proc == hqP)
797 hqE->msg4Proc = NULLP;
800 /* Add the proc to the free list */
801 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
802 rgSCHDhmHqPAdd2FreeLst(hqP);
806 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
807 * is dangerous and it expects ccchSduProc is the first
808 * DL allocation for a UE, and considering a scenario
809 * of multiple UEs contending and 1 UE per TTI, this
810 * assumption can be wronged, leading to inUse list
811 * corruption. Hence altering this check.
812 * A better approach would be do avoid having this
813 * special handling for ccchSduProc, streamline
814 * it with the usual approach. */
815 if (hqE->ccchSduProc == hqP)
817 hqE->ccchSduProc = NULLP;
818 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
819 * in inUse list, Hence need not to delete from inUse list*/
820 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
822 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
823 rgSCHDhmHqPDelFrmInUseLst(hqP);
827 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
831 /* Add the proc to the free list */
832 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
833 rgSCHDhmHqPAdd2FreeLst(hqP);
838 /* extra:check if other TB is also free for allocation then
839 * add it to FREE List */
840 switch(hqP->tbInfo[othrTbIdx].state)
843 /* Remove the element from the inUse Queue */
844 /* Freeing up the HARQ proc blocked for
845 * indefinite time in case of Retx */
846 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
848 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
849 rgSCHDhmHqPDelFrmInUseLst(hqP);
854 rgEmtcsetNullSubFrm(hqP);
856 /* Add the proc to the free list */
857 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
858 rgSCHDhmHqPAdd2FreeLst(hqP);
860 if (hqE->free.count > 8)
863 printf("\nDEBUG --> SCH: Crashing invalid hq count after free \n");
864 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
869 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
872 cmnHqDl->spsAction = 0;
873 cmnHqDl->isSpsActv = FALSE;
874 cmnHqDl->isSpsSvcSchd = FALSE;
879 /* Remove the element from the inUse Queue */
880 /* Freeing up the HARQ proc blocked for
881 * indefinite time in case of Retx */
882 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
884 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
885 rgSCHDhmHqPDelFrmInUseLst(hqP);
893 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
896 } /* rgSCHDhmRlsHqpTb */
899 * @brief This function releases a HARQ process.
903 * Function: rgSCHDhmRlsHqProc
904 * Purpose: This function returns a HARQ process to HARQ Entity
905 * in the DL direction.
907 * 1. Add the HARQ process to the free queue.
908 * Invoked by: scheduler and HARQ processing
910 * @param[in] RgDlHqProc *hqP
914 Void rgSCHDhmRlsHqProc(RgSchDlHqProcCb *hqP)
919 /* THIS FUNCTION IS NOT CALLED */
920 if (hqP->hqE->ue != NULLP)
922 RgSchUeCb *ueCb = hqP->hqE->ue;
923 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
924 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
925 uint8_t cqi = dlUe->mimoInfo.cwInfo[0].cqi;
926 /* to get retransmission, decreasing transmission counter */
927 uint16_t numDlRetx = hqP->tbInfo[0].txCntr-1;
928 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
930 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
935 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
938 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
941 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
944 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
947 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
948 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
949 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
950 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
951 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
953 #endif /* MAC_SCH_STATS */
957 rgEmtcsetNullSubFrm(hqP);
959 rgSCHDhmHqPDelFrmInUseLst(hqP);
960 rgSCHDhmHqPAdd2FreeLst(hqP);
966 } /* rgSCHDhmRlsHqProc */
970 * @brief This function gets HARQ process with the given ID.
974 * Function: rgSCHDhmGetHqProcFrmId
975 * Purpose: This function returns the HARQ process with the given ID.
978 * @param[in] RgSchUeCb *ue
979 * @param[in] uint8_t idx
980 * @param[in] RgDlHqProc **hqP
982 * -# ROK if successful
983 * -# RFAILED otherwise
986 S16 rgSCHDhmGetHqProcFrmId(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t idx,RgSchDlHqProcCb **hqP)
990 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
991 /* Pick the proc based on the index provided */
992 *hqP = &(hqE->procs[idx]);
995 } /* rgSCHDhmGetHqProcFrmId */
998 * @brief This function gets SPS HARQ process from the given time
1002 * Function: rgSCHDhmSpsDlGetHqProc
1003 * Purpose: This function returns the SPS HARQ process for the given time
1005 * @param[in] RgSchUeCb *ue
1006 * @param[in] CmLteTimingInfo timingInfo
1007 * @return RgSchDlHqProcCb control block
1010 RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
1014 RgSchDlHqProcCb *hqProc = NULLP;
1015 CmLList *tmp = NULLP;
1017 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1019 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1023 /* No Harq Process available in the free queue. */
1027 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.slot)/
1028 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1031 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1033 /* If the HARQ process is in the free list, retrieve the process */
1034 while (hqProc->procId != idx)
1036 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1041 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1046 /* No Harq Process available in the free queue. */
1050 hqProc->tbInfo[0].timingInfo = timingInfo;
1051 hqProc->tbInfo[1].timingInfo = timingInfo;
1053 /* Remove the element from the free Queue */
1054 //cmLListDelFrm(&hqE->free, tmp);
1055 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1057 /* Add the element into the inUse Queue as well */
1058 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1059 rgSCHDhmHqPAdd2InUseLst(hqProc);
1062 rgSCHLaaResetDlHqProcCb(hqProc);
1066 } /* rgSCHDhmSpsDlGetHqProc */
1067 #endif /* LTEMAC_SPS */
1070 /** * @brief Handler for handling TA.
1074 * Function : rgSCHDhmFdbkIndHndlTa
1076 * This function handles the TA state and values based on the
1077 * feedback indication received.
1079 * @param[in] RgSchDlHqProcCb *hqP
1080 * @param[in] uint8_t tbIdx
1081 * @param[in] uint8_t fdbk
1085 static Void rgSCHDhmFdbkIndHndlTa(RgSchDlHqProcCb *hqP,uint8_t tbIdx,uint8_t fdbk,Bool maxHqRetxReached)
1090 ueCb = hqP->hqE->ue;
1095 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1096 hqP->tbInfo[tbIdx].taSnt = FALSE;
1097 /* To prevent duplicate inserts of ueCb into TA list */
1098 if (ueCb->taLnk.node == NULLP)
1100 ueCb->taLnk.node = (PTR)ueCb;
1101 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1106 DU_LOG("\nERROR --> SCH : Trying to add CRNTI:%d into TA"
1107 "ACK List twice", ueCb->ueId);
1113 /* If Ta was sent and its the final NACK, then reset only the
1114 * taState to IDLE and not the value */
1115 /* Changed handling in case maxhqretx is reached for TA */
1116 if(TRUE == maxHqRetxReached)
1118 hqP->tbInfo[tbIdx].taSnt = FALSE;
1119 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1121 rgSCHUtlReTxTa(cell, ueCb);
1122 DU_LOG("\nERROR --> SCH : Nack Rcvd for TA. Max Tries Attempted");
1126 /* If Ta was sent and its the final NACK, then reset only the
1127 * taState to IDLE and not the value */
1128 if(TRUE == maxHqRetxReached)
1130 hqP->tbInfo[tbIdx].taSnt = FALSE;
1131 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1133 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1134 * issue for VoLTE call */
1135 rgSCHUtlDlTARpt(cell, ueCb);
1144 } /* rgSCHDhmFdbkIndHndlTa */
1146 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1147 /** * @brief Handler for scheduling TA.
1151 * Function : rgSCHDhmShcdTa
1153 * This function is called by scheduler when resource allocation
1154 * for TA transmission is done.
1156 * @param[in] RgSchUeCb *ue
1157 * @param[out] RgSchDlHqTbCb *tbInfo
1161 Void rgSCHDhmSchdTa(RgSchUeCb *ueCb,RgSchDlHqTbCb *tbInfo)
1164 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1165 ueCb->dl.taCb.numRemSf = 2;
1166 tbInfo->schdTa.pres = PRSNT_NODEF;
1167 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1170 } /* rgSCHDhmSchdTa */
1173 /** * @brief Handler for fetching Harq Proc given the feeback information.
1177 * Function : rgSCHDhmHqProcByFdbkTime
1179 * This function shall fetch all the harq proc having the feedback
1180 * timing information.
1182 * @param[in] RgSchDlHqEnt *hqE
1183 * @param[in] CmLteTimingInfo timeInfo
1184 * @param[in] Bool *isMsg4
1185 * @param[out] RgSchDlHqProcCb **hqPrcs
1186 * @param[out] uint8_t *numTbs
1187 * @param[out] S8 *tbStrtIdx
1188 * @param[out] uint8_t *cntHqPrcs
1191 static S16 rgSCHDhmHqProcByFdbkTime
1194 CmLteTimingInfo timeInfo,
1196 RgSchDlHqProcCb **hqPrcs,
1203 RgSchDlHqTbCb *tbCb;
1204 RgSchDlHqProcCb *hqP;
1205 CmLteTimingInfo schdSfTime;
1206 RgSchTddDlAscSetIdxK ascIdx;
1217 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1220 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1221 tbStrtIdx[*cntHqPrcs] = 0;
1222 numTbs[*cntHqPrcs] = 1;
1227 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.slot];
1228 noFdbks = ascIdx.numFdbkSubfrms;
1230 for(idx=0; idx<noFdbks; idx++)
1232 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1233 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1234 * serving the purpose */
1235 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1236 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1237 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1241 hqP = (RgSchDlHqProcCb*)node->node;
1244 numTbs[*cntHqPrcs] = 0;
1245 tbStrtIdx[*cntHqPrcs] = -1;
1246 for (i = 0; i < 2; i++)
1248 /* Extra:check which TB is waiting for feedback */
1249 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1251 if (tbStrtIdx[*cntHqPrcs] == -1)
1253 tbStrtIdx[*cntHqPrcs] = i;
1255 numTbs[*cntHqPrcs]++;
1258 if (numTbs[*cntHqPrcs] > 0)
1260 hqPrcs[*cntHqPrcs] = hqP;
1265 /* AN REP Hq Procs */
1266 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1269 tbCb = (RgSchDlHqTbCb *)(node->node);
1272 numTbs[*cntHqPrcs] = 0;
1273 tbStrtIdx[*cntHqPrcs] = -1;
1274 for (i = 0; i < 2; i++)
1276 /* Extra:check which TB is waiting for feedback */
1277 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1279 if (tbStrtIdx[*cntHqPrcs] == -1)
1281 tbStrtIdx[*cntHqPrcs] = i;
1283 numTbs[*cntHqPrcs]++;
1286 if (numTbs[*cntHqPrcs] == 2)
1290 if (numTbs[*cntHqPrcs] > 0)
1292 hqPrcs[*cntHqPrcs] = hqP;
1304 /** * @brief Handler for fetching Harq Proc given the timming information.
1308 * Function : rgSCHDhmHqProcByTime
1310 * This function shall fetch the harq proc using the timing information.
1312 * @param[in] RgSchDlHqEnt *hqE
1313 * @param[in] CmLteTimingInfo timeInfo
1314 * @param[in] Bool *isMsg4
1315 * @param[out] uint8_t *numTbs
1316 * @param[out] S8 *tbStrtIdx
1317 * @return RgSchDlHqProcCb*
1318 * -# RgSchDlHqProcCb*
1321 RgSchDlHqProcCb *rgSCHDhmHqProcByTime(RgSchDlHqEnt *hqE,CmLteTimingInfo timeInfo,Bool *isMsg4,RgSchDlSf *sf)
1325 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1328 return (hqE->msg4Proc);
1336 /** * @brief Handler for handling the harq transaction failure.
1340 * Function : rgSCHDhmHqTbTrnsFail
1342 * This function handled the harq TB transaction failure :
1343 * - If retries have not reached maximum, add to the reTx Q.
1344 * - else do error recovery.
1346 * @param[in] RgSchCellCb *cell
1347 * @param[in] RgSchDlHqProcCb *hqP
1348 * @param[in] uint8_t tbCnt
1349 * @param[out] Bool *isMaxRetx
1354 Void rgSCHDhmHqTbTrnsFail(RgSchCellCb *cell,RgSchDlHqProcCb *hqP,uint8_t tbCnt,Bool *isMaxRetx)
1361 /* Fetch the maximum number of harq transmissions */
1362 if (hqE->msg4Proc == hqP)
1365 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1367 DU_LOG("\nDEBUG --> SCH : rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1368 hqP->hqE->raCb->tmpCrnti);
1369 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1373 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1377 maxHqTx = hqE->maxHqTx;
1380 #ifdef MAC_SCH_STATS
1381 if (hqE->ue != NULLP)
1383 RgSchUeCb *ueCb = hqE->ue;
1384 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1385 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1386 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1387 static uint32_t retxCnt = 0;
1391 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1393 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1394 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1396 #endif /* MAC_SCH_STATS */
1398 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1399 /* Reset the PDCCH reference */
1401 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1403 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1405 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1408 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1409 * for the UE. Addtion to the retransmission queue will be done on
1410 * HARQ RTT timer expiry.--*/
1411 switch(hqP->tbInfo[tbCnt ^ 1].state)
1414 /*As the first TB is ACKED we have not started HARQ RTT for the
1415 * HqP, so start it here.*/
1416 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1417 rgSCHDhmHqPDelFrmInUseLst(hqP);
1419 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1422 /* Integration fix */
1423 /* Setting cntrRetxAllocFail to MAX value here */
1424 /* Since the hqP entry is already deleted from inUse list of HqEntity
1425 setting the value here will ensure the entry is not deleted
1426 again during release harq proc */
1427 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1428 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1430 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1431 if (hqP->tbInfo[1].txCntr)
1433 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1439 /*As the first TB is NACKED we have already started HARQ RTT for the
1440 * HqP, so dont start it here, just delete from in use queue.*/
1441 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1442 rgSCHDhmHqPDelFrmInUseLst(hqP);
1445 /*As this is the first TB to be fed back and is NACKED start
1446 * the HARQ RTT here.*/
1448 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1454 /* extra:check if already removed as part of other TB processing
1455 * then donot remove from InUse Q */
1456 /* Check if other TB is not waiting for feedback.
1457 * Makinf sure hqP is present in inUse Queue until
1458 * it is fedback for all its TBs */
1459 switch(hqP->tbInfo[tbCnt ^ 1].state)
1462 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1463 if(hqE->msg4Proc != hqP)
1465 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1466 rgSCHDhmHqPDelFrmInUseLst(hqP);
1468 /* Retransmission needs to be done. Add to the scheduler Q */
1469 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1472 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1473 if(hqE->msg4Proc != hqP)
1475 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1476 rgSCHDhmHqPDelFrmInUseLst(hqP);
1480 /* Retransmission needs to be done. Add to the scheduler Q */
1482 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1490 /* Failure Notification */
1491 if (hqE->msg4Proc == hqP)
1493 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1494 rgNumMsg4FailMaxRetx++;
1496 hqE->cell->tenbStats->sch.msg4Fail ++;
1499 /* Perform RAM MSG4 done processing */
1500 DU_LOG("\nDEBUG --> SCH : rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1501 hqP->hqE->raCb->tmpCrnti);
1502 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1506 /* Release the Harq Proc */
1507 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1513 } /* rgSCHDhmHqTbTrnsFail */
1515 uint32_t rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1516 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1519 /** * @brief Function to decode the position of HarqFb for M=1.
1523 * Function : rgSchGetHqFdbkPosForM1
1525 * @param[in] RgSchUeCb *ue,
1526 * @param[in] RgSchDlHqProcCb *hqP,
1527 * @param[in] uint8_t *isAck,
1528 * @param[in] RgTfuHqInfo *fdbk,
1529 * @param[in] uint8_t tbIdx,
1530 * @param[in] RgSchTddANInfo *anInfo;
1533 static Void rgSchGetHqFdbkPosForM1
1536 RgSchDlHqProcCb *hqP,
1540 RgSchTddANInfo *anInfo
1545 /* handle pusch and pucch cases */
1546 /* PUSCH:: Fdbks are in the increasing order
1547 * of servCellIdx as per 36.212 section 5.2.26*/
1548 switch(ue->f1bCsAVal)
1550 case RG_SCH_A_VAL_2:
1552 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1554 *isAck = fdbk->isAck[1];/*SCell*/
1558 *isAck = fdbk->isAck[0];/*PCell*/
1562 case RG_SCH_A_VAL_3:
1564 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1566 uint8_t cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1567 hqP->hqE->cell->cellId,
1570 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1571 {/*SCell - mimo mode*/
1572 if(TRUE == fdbk->isPusch)
1574 *isAck = fdbk->isAck[tbIdx + 1];
1578 *isAck = fdbk->isAck[tbIdx];
1582 {/*SCell - siso mode*/
1583 *isAck = fdbk->isAck[2];
1587 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1588 {/*Primary Cell - mimo mode*/
1589 *isAck = fdbk->isAck[tbIdx];
1592 {/*Primary Cell - siso mode*/
1593 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1595 /* If fdbk is on PUSCH but its not an SPS occasion*/
1596 *isAck = fdbk->isAck[0];
1600 /* If fdbk is on PUCCH or its an SPS occasion*/
1601 *isAck = fdbk->isAck[2];
1607 case RG_SCH_A_VAL_4:
1609 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1611 *isAck = fdbk->isAck[tbIdx + 2];
1615 *isAck = fdbk->isAck[tbIdx];
1624 }/* End of rgSchGetHqFdbkPosForM1 */
1626 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1630 * Function : rgSchGetHqFdbkPosForM234
1632 * @param[in] RgSchUeCb *ue,
1633 * @param[in] RgSchDlHqProcCb *hqP,
1634 * @param[in] uint8_t *isAck,
1635 * @param[in] RgTfuHqInfo *fdbk,
1636 * @param[in] uint8_t tbIdx,
1637 * @param[in] RgSchTddANInfo *anInfo;
1638 * @param[in] CmLteTimingInfo timeInfo;
1641 static Void rgSchGetHqFdbkPosForM234
1644 RgSchDlHqProcCb *hqP,
1648 RgSchTddANInfo *anInfo,
1650 CmLteTimingInfo timeInfo
1655 RgSchTddANInfo *pCellAnInfo;
1660 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1661 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1663 if(TRUE == fdbk->isPusch)
1667 if (anInfo->wUlDai == 3)
1669 incr = anInfo->wUlDai;
1675 if(1 == anInfo->ulDai)
1677 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1678 hqP->tbInfo[tbIdx].tbIdx + incr;
1682 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1687 if(1 == anInfo->ulDai)
1689 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1691 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1695 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1700 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1708 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1709 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1715 /* SPS occasion feedback in case of M > 2 will
1716 * be always present in the index 0*/
1718 if(hqP->spsN1PucchRes.pres == TRUE)
1719 {/* SPS occasion hq proc */
1723 if((NULLP != pCellAnInfo) &&
1724 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
1726 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1728 {/* NO SPS occasion was present in the bundle*/
1729 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1734 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
1738 *isAck = fdbk->isAck[fdbkIdx];
1740 static RgSchDlHqProcCb *temp = NULLP;
1741 if (temp != hqP->tbInfo[tbIdx].hqP)
1743 statsCnt = statsCnt % 10000;
1744 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
1745 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
1746 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.slot;
1747 dlHqStats[statsCnt].ack = *isAck;
1748 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
1749 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;
1751 dlHqStats[statsCnt].ulDai = incr;
1752 if(TRUE == fdbk->isPusch)
1754 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
1758 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
1762 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
1763 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
1764 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
1765 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
1766 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
1767 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
1768 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
1769 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
1772 temp = hqP->tbInfo[tbIdx].hqP;
1777 }/*rgSchGetHqFdbkPosForM234*/
1781 * @brief Handler for HARQ feedback received for DL transmission.
1785 * Function : rgSCHDhmHqFdbkInd
1787 * This function shall act on the feedback received from TOM for DL
1788 * transmission. If the feedback for msg4 is final (after max transmissions
1789 * or ACK) inform RAM that Msg4 transmission is done.
1792 * @param[in] Void *cb
1793 * @param[in] uint8_t cbType
1794 * @param[in] RgSchCellCb cellCb
1795 * @param[in] CmLteTimingInfo timeInfo
1796 * @param[in] TfuHqInfo *fdbk
1797 * @param[in] RgInfRlsHqInfo *rlsHqBufs
1798 * @param[in] RgSchErrInfo *err
1803 S16 rgSCHDhmHqFdbkInd
1807 RgSchCellCb *cellCb,
1808 CmLteTimingInfo timeInfo,
1810 RgInfRlsHqInfo *rlsHqBufs,
1814 RgSchCellCb *sCell = NULLP;
1816 /*ccpu00127339 - MOD - change to avoid the crash*/
1817 RgSchUeCb *ue = NULLP;
1819 Bool isMsg4 = FALSE;
1820 RgSchRaCb *raCb = NULLP;
1822 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
1823 * given feedback at a time */
1824 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
1825 uint8_t numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
1826 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
1829 RgSchTddANInfo *anInfo = NULLP;
1832 RgrTddAckNackMode ackNackMode;
1834 RgSchDlSf *nxtDlsf = NULLP;
1835 /* uint8_t rcvCnt = 0; */
1836 CmLteTimingInfo nxtfrm = {0,0};
1838 Bool maxHqRetxReached;
1840 Bool hasRelPdcch = FALSE;
1843 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1844 RgSchTddDlAscSetIdxK ascIdx;
1848 #ifdef LTEMAC_SPS_AN_MUX
1849 Bool isPusch = FALSE;
1852 /* Subframes in which transmissions are scheduled and whose feedback can come
1853 * in this subframe. Used only for Multiplexing mode */
1854 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
1855 #ifdef RGSCH_SPS_STATS
1856 RgSchCmnDlHqProc *cmnHqDl;
1860 uint8_t sCellActCePres = 0;
1862 /* LTEMAC_SPS_AN_MUX*/
1863 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
1865 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
1867 raCb = (RgSchRaCb *)(cb);
1868 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
1870 /* ccpu00139061 Fix */
1871 rnti = raCb->tmpCrnti;
1875 ue = (RgSchUeCb *)(cb);
1876 ackNackMode = ue->dl.ackNackMode;
1877 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
1879 #ifdef LTEMAC_SPS_AN_MUX
1880 isPusch = fdbk->isPusch;
1884 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
1891 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
1892 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.slot];
1893 noFdbks = ascIdx.numFdbkSubfrms;
1895 #ifdef LTEMAC_SPS_AN_MUX
1896 /* Calculate the subframe time at which transmissions should have happened to
1897 * receive feedback in this subframe */
1898 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
1900 for(idx=0; idx<noFdbks; idx++)
1902 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1903 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1904 * serving the purpose */
1905 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
1910 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
1911 tbStrtIdx, &hqCnt,hqE->cell);
1912 /* Fetch the harqProc from the inUse list */
1914 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
1918 err->errType = RGSCHERR_DHM_FDBK_IND;
1919 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
1923 /* ccpu00147469 : This code is moved below as here this code always try to
1924 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
1928 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
1930 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
1936 #ifdef LTEMAC_SPS_AN_MUX
1937 /* Check if feedback came on configured UL SPS grant in Muxing mode */
1938 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
1942 /* Pick the valid feedbacks out of M feedbacks */
1943 for(idx=0; idx<noFdbks; idx++)
1945 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
1946 * and no release pdcch is sent in prevTime */
1947 /* TODO: SPS_TDD: Check this while testing */
1948 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
1949 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
1950 schdSfTime[idx])) &&
1951 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
1953 /* Discard the feedback which is corresponding to a subframe in
1954 * which no DL transmission took place */
1956 while(tmpIdx < noFdbks)
1958 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1959 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
1965 } /* end of for loop */
1966 } /* end of configured UL SPS grant check */
1978 for(idx=0;idx < hqCnt; idx++)
1980 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
1984 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
1985 hqPrcs[idx]->hqE->cell->cellId,ue);
1987 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
1991 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
1993 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
1997 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
1998 "Ack Rcvd. No Ack/Nack feedback available \n"));
2003 sCell = hqPrcs[idx]->hqE->cell;
2004 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2005 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2006 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2008 /* Fix : syed MultiUe per TTI crash in TA List. */
2010 maxHqRetxReached = FALSE;
2011 /* Remove the harq process from the subframe */
2012 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2016 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2019 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2021 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2022 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2024 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2028 /* TODO: review for TM4 and CA interaction */
2029 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2031 isAck = fdbk->isAck[!tbCnt];
2035 isAck = fdbk->isAck[tbCnt];
2044 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2048 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2054 /* revanth tweakin AN PUSCH to ACK always */
2055 if (hqPrcs[idx]->isPuschFdbk)
2061 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2062 if(cellCb->ulDlCfgIdx != 5)
2064 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2065 cellCb, sf, &nxtDlsf, &nxtfrm);
2067 /* Keep a tab on how many ACKs or NACKs we have received */
2068 if (isAck == TFU_HQFDB_ACK)
2070 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2071 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2073 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2074 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2076 /* Do not update the Ul Trans Time in case of raCb */
2079 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2081 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2085 else if (isAck == TFU_HQFDB_NACK)
2087 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2088 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2090 sCell->tenbStats->sch.dlNack[tbCnt]\
2091 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2092 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2093 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2095 /* Do not update the Ul Trans Time in case of raCb */
2098 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2100 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2101 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2105 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2107 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2113 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2115 sCell->tenbStats->sch.dlDtx[tbCnt]\
2116 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2119 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2123 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2125 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2130 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2132 if(isAck == TFU_HQFDB_ACK)
2134 gSCellTb1AckCount++;
2135 gSCellTb2AckCount++;
2136 }else if(isAck == TFU_HQFDB_NACK)
2138 gSCellTb1NackCount++;
2139 gSCellTb2NackCount++;
2142 gSCellTb1DtxCount++;
2143 gSCellTb2DtxCount++;
2148 if(isAck == TFU_HQFDB_ACK)
2150 gPCellTb1AckCount++;
2151 gPCellTb2AckCount++;
2152 }else if(isAck == TFU_HQFDB_NACK)
2154 gPCellTb1NackCount++;
2155 gPCellTb2NackCount++;
2158 gPCellTb1DtxCount++;
2159 gPCellTb2DtxCount++;
2163 /* Check if this is repeating UE */
2164 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2166 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2167 /* Check if last repetition */
2168 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2170 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2171 /* Update feedback time for this hqP TB so that
2172 * next subframe its picked up */
2173 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2175 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2176 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2180 /* For a repeating UE take the decision here */
2181 /* For a repeating UE take the decision here */
2182 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2183 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2185 isAck = TFU_HQFDB_ACK;
2187 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2188 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2190 isAck = TFU_HQFDB_DTX;
2194 isAck = TFU_HQFDB_NACK;
2196 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2200 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2203 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2204 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2205 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2208 /* ACK or NACK received for SPS ACTV PDCCH
2209 * Hence consider SPS ACTVN PDCCH received successfully */
2210 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2213 if(TFU_HQFDB_ACK == isAck)
2220 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2222 /* Inform Random Access Module regarding the ack received */
2225 /*RRC Connection Setup failure issue where RRC connection
2226 * setup was not reaching UE due to message 4 HARQ failure */
2227 #ifdef XEON_SPECIFIC_CHANGES
2228 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2230 rgSCHRamMsg4Done(cellCb, raCb);
2233 else /*ccpu00114124- HARQ Release for Msg4 */
2236 /*Update feedback history for every Tx/Retx */
2237 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2239 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2240 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2242 /* Store activation CE presence as it is required later to start
2243 *activation delay timer */
2244 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2246 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2252 /* If this Msg4 DTX, there will be
2253 * no DlHqProc as it has its own HarqProc */
2256 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2257 maxHqRetxReached = hqRls;
2259 if ((isMsg4 == FALSE))
2261 /*Update feedback history for every Tx/Retx */
2262 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2265 if (isMsg4 == FALSE)
2267 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2268 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2275 /* MS_WORKAROUND: to increase Harq Fail Counter .
2276 The status field is required for tracking the number of harq faliures at MAC*/
2279 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2280 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2284 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2285 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2287 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2288 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2289 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2293 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2295 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2298 /* Handle Scell activation */
2299 if (TRUE == sCellActCePres)
2301 /* Primary Cellcb needs to be retrived
2302 * if the feedback is coming on pusch of
2303 * sec cell. THis needs to be considered
2305 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2311 hqPrcs[idx]->cwSwpEnabled = FALSE;
2313 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2315 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2316 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2317 hqPrcs[idx]->procId;
2318 rlsHqBufs->numUes++;
2321 hqPrcs[idx]->isPuschFdbk = 0;
2326 /*it is possible for some TDD configurations (like TDD cfg 5)
2327 * to have multiple feedback for 13 subframes before. It is
2328 * possible in such a case to have a release sent after data
2329 * thus running into a situation where we are receiving feedback
2330 * for both data and relese pdcch
2333 if ( (hqCnt == 0) ||
2334 (hasRelPdcch && rcvCnt > hqCnt)
2337 if (ue && hasRelPdcch)
2339 /* Bool found = FALSE; */
2341 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2351 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2352 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2354 CmLteTimingInfo txTime;
2355 uint8_t ulDlCfgIdx = 0;
2356 uint8_t maxFdbks = 0;
2359 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2361 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2365 for(itr=0; itr< maxFdbks; itr++)
2368 /* Handling the case of only SPS release pdcch
2369 * and no other scheduling in both the serving cells
2371 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2372 {/* Using the sorted K table */
2373 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2374 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2378 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2379 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.slot].subfrmNum[itr]);
2382 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2385 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2388 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2390 isAck = fdbk->isAck[0];
2393 isAck = fdbk->isAck[2];
2397 /* M > 1 same below logic apply.
2398 If SPS occasion and rel pdcch is present
2399 SPS occasion after SPS release cannot
2404 isAck = fdbk->isAck[itr];
2407 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2409 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2410 /* Remove release PDCCH from the subframe */
2411 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2412 sf->relPdcch = NULLP;
2422 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2423 /* Remove release PDCCH from the subframe */
2424 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2425 sf->relPdcch = NULLP;
2427 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2430 if ( found == FALSE )
2432 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2433 DU_LOG("\nERROR --> SCH : NO HARQ proc available for feedback:timeInfo:snf %d,slot %d",
2434 ue->ueId,timeInfo.sfn, timeInfo.slot);
2435 err->errType = RGSCHERR_DHM_FDBK_IND;
2436 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2441 #endif /* LTEMAC_SPS */
2442 /* Initialise the Ack/Nack feedback */
2443 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2444 scheduling. So added a condition !isMsg4 to avoid calling the function
2445 rgSCHUtlInitUeANFdbkInfo*/
2446 if((ue) && (!anUpd) && (!isMsg4))
2449 /* TODO:: Initi the anInfo all the serving cells */
2450 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2452 if(ue->cellInfo[idx])
2454 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2455 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2456 * else don't do anything. basically continue for next serving
2460 rgSCHUtlInitUeANFdbkInfo(anInfo);
2465 rgSCHUtlInitUeANFdbkInfo(anInfo);
2471 //#endif /* LTEMAC_SPS */
2474 /** * @brief Handler for HARQ feedback received for DL transmission.
2478 * Function : rgSCHDhmPrcFdbkForTb
2480 * Process Hq Prc Fdbk for a TB
2482 * @param[in] RgSchCellCb *cell
2483 * @param[in] RgTfuHarqAckIndInfo *fdbk
2484 * @param[in] RgSchErrInfo *err
2489 S16 rgSCHDhmPrcFdbkForTb
2493 RgSchDlHqProcCb *hqP,
2498 CmLteTimingInfo timingInfo,
2500 RgInfRlsHqInfo *rlsHqBufs,
2505 Inst inst = cell->instIdx;
2507 #ifdef RGSCH_SPS_STATS
2508 RgSchCmnDlHqProc *cmnHqDl;
2511 RgSchRaCb *raCb = NULLP;
2513 Bool hqFreed =FALSE;
2514 Bool maxHqRetxReached = FALSE;
2515 RgSchCmnDlUe *ueDl = NULLP;
2516 RgSchCellCb *sCell = hqP->hqE->cell;
2518 RgSchEmtcDlSf *emtcSf;
2519 CmLteTimingInfo frm = timingInfo;
2524 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2527 /* Fix : syed MultiUe per TTI crash in TA List. */
2528 maxHqRetxReached = FALSE;
2530 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2531 * TODO: Need to enhance this in case of TM4 testing,
2532 * when cwSwap flag is considered. */
2534 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2535 tbCnt=%d , isAck=%d",tbCnt,isAck));
2536 if (isAck == TFU_HQFDB_ACK)
2538 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2540 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2541 /* Do not update the Ul Trans Time in case of raCb */
2544 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2546 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2552 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2553 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2558 else if (isAck == TFU_HQFDB_NACK)
2560 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2561 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2562 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2563 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2564 /* Do not update the Ul Trans Time in case of raCb */
2567 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2568 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2570 sCell->tenbStats->sch.dlNack[tbCnt]\
2571 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2578 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2580 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2581 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2584 /* Added Dl TB count for NACKED data*/
2586 if(hqP->tbInfo[tbCnt].txCntr == 1)
2588 cell->dlUlTbCnt.tbTransDlFaulty++;
2594 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2595 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2596 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2599 sCell->tenbStats->sch.dlDtx[tbCnt]\
2600 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2603 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2608 /* Added Dl TB count for DTXED data*/
2610 if(hqP->tbInfo[tbCnt].txCntr == 1)
2612 cell->dlUlTbCnt.tbTransDlFaulty++;
2617 /* Check if this is repeating UE */
2618 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2620 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2627 /* For a Normal UE take the decision here */
2628 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2630 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2633 /* Process either the ACK received or max retries have occurred */
2634 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2635 if (TFU_HQFDB_ACK == isAck)
2639 /* SR_RACH_STATS : MSG4 ACK*/
2644 raCb = rgSCHDbmGetRaCb(cell, rnti);
2646 DU_LOG("\nDEBUG --> SCH: Ack Rcvd. FdbkInd for Msg4Done\n");
2647 /* Inform Random Access Module regarding the ack received */
2650 /*RRC Connection Setup failure issue where RRC connection
2651 * setup was not reaching UE due to message 4 HARQ failure */
2652 printf("\nDEBUG --> SCH: MSG4 Ack ,calling rgSCHRamMsg4Done\n");
2653 ret = rgSCHRamMsg4Done(cell, raCb);
2658 printf("\nDEBUG --> SCH: raCb is NULLP\n");
2661 else /*ccpu00114124- HARQ Release for Msg4 */
2663 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2664 /* Push this harq process back to the free queue */
2665 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2667 if(hqP->tbInfo[tbCnt].txCntr == 1)
2669 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2672 RGSCH_NULL_CHECK(cell->instIdx, ue);
2673 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2674 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2683 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2684 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2686 if(hqP->tbInfo[tbCnt].txCntr == 1)
2688 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2691 RGSCH_NULL_CHECK(cell->instIdx, ue);
2692 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2696 #ifdef XEON_SPECIFIC_CHANGES
2697 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
2701 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
2702 maxHqRetxReached = hqRls;
2708 /* MS_WORKAROUND: to increase Harq Fail Counter .
2709 The status field is required for tracking the number of harq faliures at MAC*/
2712 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2713 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2716 else if(maxHqRetxReached)
2718 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
2719 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2720 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
2725 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2726 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2728 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2729 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2730 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2734 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
2736 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
2739 } /* rgSCHDhmPrcFdbkForTb */
2740 /** * @brief Function to decode the position of HarqFb for eachCell.
2744 * Function : rgSchGetHqFdbkPos
2746 * @param[in] RgSchCellCb *cell,
2747 * @param[in] RgSchUeCb *ue,
2748 * @param[in] RgSchDlHqProcCb *hqP,
2749 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
2750 * @param[in] Bool *isAck,
2751 * @param[in] RgTfuHqInfo *fdbk,
2754 Void rgSchGetHqFdbkPos
2758 RgSchDlHqProcCb *hqP,
2759 RgrSchFrmt1b3TypEnum uciFrmtTyp,
2764 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2766 isAck[0] = fdbk->isAck[0];
2767 isAck[1] = fdbk->isAck[1];
2771 /* LAA Making all ack for LAA CELL */
2772 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
2782 /* PUSCH:: Fdbks are in the increasing order
2783 * of servCellIdx as per 36.212 section 5.2.26*/
2784 switch(ue->f1bCsAVal)
2786 case RG_SCH_A_VAL_2:
2788 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2790 isAck[0] = fdbk->isAck[1];/*SCell*/
2791 isAck[1] = fdbk->isAck[1];/*SCell*/
2795 isAck[0] = fdbk->isAck[0];/*PCell*/
2796 isAck[1] = fdbk->isAck[0];/*PCell*/
2800 case RG_SCH_A_VAL_3:
2802 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2805 uint8_t servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
2806 hqP->hqE->cell->cellId,
2809 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
2811 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
2813 { /* Sec cell is in mimo mode */
2814 /* use 0 and 1 for sec in case of pucch
2815 * and 1 and 2 in case of PUSCH as the primary cell is in
2816 * siso case as A =3 */
2819 isAck[0] = fdbk->isAck[0];
2820 isAck[1] = fdbk->isAck[1];
2822 {/* PUSCH as per 36.212 serction 5.2.26*/
2823 isAck[0] = fdbk->isAck[1];
2824 isAck[1] = fdbk->isAck[2];
2827 {/* sec cell is in siso */
2828 isAck[0] = fdbk->isAck[2];
2832 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2833 {/* primay cell is in mimo
2835 isAck[0] = fdbk->isAck[0];
2836 isAck[1] = fdbk->isAck[1];
2841 isAck[0] = fdbk->isAck[2];
2843 {/* PUSCH as per 36.212 serction 5.2.26*/
2844 isAck[0] = fdbk->isAck[0];
2850 case RG_SCH_A_VAL_4:
2852 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
2854 isAck[0] = fdbk->isAck[2];
2855 isAck[1] = fdbk->isAck[3];
2858 if(isAck[0] == TFU_HQFDB_ACK)
2860 gSCellTb1AckCount++;
2861 }else if(isAck[0] == TFU_HQFDB_NACK)
2863 gSCellTb1NackCount++;
2866 gSCellTb1DtxCount++;
2869 if(isAck[1] == TFU_HQFDB_ACK)
2871 gSCellTb2AckCount++;
2872 }else if(isAck[1] == TFU_HQFDB_NACK)
2874 gSCellTb2NackCount++;
2877 gSCellTb2DtxCount++;
2885 isAck[0] = fdbk->isAck[0];
2886 isAck[1] = fdbk->isAck[1];
2889 if(isAck[0] == TFU_HQFDB_ACK)
2891 gPCellTb1AckCount++;
2892 }else if(isAck[0] == TFU_HQFDB_NACK)
2894 gPCellTb1NackCount++;
2897 gPCellTb1DtxCount++;
2900 if(isAck[1] == TFU_HQFDB_ACK)
2902 gPCellTb2AckCount++;
2903 }else if(isAck[1] == TFU_HQFDB_NACK)
2905 gPCellTb2NackCount++;
2908 gPCellTb2DtxCount++;
2923 }/* End of rgSchGetHqFdbkPos */
2925 Void rgSchGetHqFdbkPosFormat3
2927 RgSchDlHqProcCb *hqP,
2932 uint8_t cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
2933 isAck[0] = (uint8_t)fdbk[cellIdx];
2934 isAck[1] = (uint8_t)fdbk[cellIdx + 1];
2937 /** * @brief Handler for HARQ feedback received for DL transmission.
2941 * Function : rgSCHDhm5gtfHqFdbkInd
2943 * This function shall act on the feedback received from TOM for DL
2944 * transmission. If the feedback for msg4 is final (after max transmissions
2945 * or ACK) inform RAM that Msg4 transmission is done.
2948 * @param[in] Void *cb
2949 * @param[in] uint8_t cbType
2950 * @param[in] RgSchCellCb *cell
2951 * @param[in] RgTfuHarqAckIndInfo *fdbk
2952 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2953 * @param[in] RgSchErrInfo *err
2958 S16 rgSCHDhm5gtfHqFdbkInd
2962 CmLteTimingInfo timingInfo,
2967 RgSchDlHqProcCb *hqP = NULLP;
2968 CmLList *node = NULLP;
2972 Bool isMsg4 = FALSE;
2975 uint8_t hqPCount = 0;
2976 RgInfRlsHqInfo *rlsHqBufs = NULLP;
2978 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
2980 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
2982 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
2984 hqPCount = lnk->count;
2989 hqP = (RgSchDlHqProcCb *)node->node;
2991 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
2992 procId = hqP->procId;
2994 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2996 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
2998 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
2999 timingInfo, fdbk, rlsHqBufs, err);
3001 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3003 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3004 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3006 rlsHqBufs->numUes++;
3012 } /* rgSCHDhm5gtfHqFdbkInd */
3014 /** * @brief Handler for HARQ feedback received for DL transmission.
3018 * Function : rgSCHDhmHqFdbkInd
3020 * This function shall act on the feedback received from TOM for DL
3021 * transmission. If the feedback for msg4 is final (after max transmissions
3022 * or ACK) inform RAM that Msg4 transmission is done.
3025 * @param[in] Void *cb
3026 * @param[in] uint8_t cbType
3027 * @param[in] RgSchCellCb *cell
3028 * @param[in] RgTfuHarqAckIndInfo *fdbk
3029 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3030 * @param[in] RgSchErrInfo *err
3035 S16 rgSCHDhmHqFdbkInd
3040 CmLteTimingInfo timingInfo,
3042 RgInfRlsHqInfo *rlsHqBufs,
3046 RgSchDlHqTbCb *tbCb;
3047 RgSchDlHqEnt *hqE = NULLP;
3048 RgSchDlHqProcCb *hqP = NULLP;
3049 CmLList *node = NULLP;
3051 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3052 RgSchUeCb *ue = NULLP;
3056 Bool isMsg4 = FALSE;
3057 RgSchRaCb *raCb = NULLP;
3059 /* Added Insure Fixes Of UR.Initialized procId */
3061 /* DTX Change: Bool is converted into uint8_t*/
3062 uint8_t isAck[2]={0}; /*Changed to Array of 2*/
3064 uint8_t hqPCount = 0;
3067 CmLteTimingInfo fdbkRcptTime = timingInfo;
3068 #ifdef RGSCH_SPS_STATS
3069 RgSchCmnDlHqProc *cmnHqDl;
3073 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3075 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3077 /* Get the subframe associated with the feedback */
3078 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3079 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3080 * serving the purpose */
3081 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3083 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3084 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3086 raCb = (RgSchRaCb *)(cb);
3088 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3094 rnti = raCb->tmpCrnti;
3098 ue = (RgSchUeCb *)(cb);
3099 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3101 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3104 hqPCount = lnk->count;
3107 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3112 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3113 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3114 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3115 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3116 from get CQI from cmInfo->cqi
3117 from cmInfo get iTbs cmInfo->iTbs[0]
3118 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3119 Update stats in cellCb
3120 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3121 if (fdbk->isAck == TRUE)
3122 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3124 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3125 DL Ack/Nack statistics
3127 #ifdef MAC_SCH_STATS
3128 if (hqE->ue != NULLP)
3130 RgSchUeCb *ueCb = hqE->ue;
3131 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3132 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3133 uint8_t tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3134 static uint32_t retxCnt = 0;
3136 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3138 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3143 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3145 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3146 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3148 #endif /* MAC_SCH_STATS */
3150 /* Fetch the harqProc from the inUse list */
3152 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3153 /* Call Common module with the feedback information */
3154 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3156 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3158 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3161 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3162 {/* Feedback for SPS Release on PCell
3163 If Pcell is in mimo, feedback index will be 0
3165 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3167 isAck[0] = fdbk->isAck[0];
3170 isAck[0] = fdbk->isAck[2];
3173 /* Not releasing pdcch here
3174 * as it is already done at the time of
3176 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3183 DU_LOG("\nERROR --> SCH : CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3184 "sfn %d slot %d", ue->ueId, timingInfo.sfn,
3189 isAck[0] = fdbk->isAck[0];
3190 /* Note: Since relPdcchFbkTimimg matches with the recieved
3191 * feedback, assumed that feedback is for release PDCCH */
3192 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3194 /* Remove release PDCCH from the subframe */
3195 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3196 sf->relPdcch = NULLP;
3201 #endif /* LTEMAC_SPS */
3203 /* Remove the harq process from the subframe */
3204 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3205 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3218 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3220 hqP = (RgSchDlHqProcCb *)node->node;
3222 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3224 procId = hqP->procId;
3226 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3228 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3229 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3231 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3233 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3238 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3240 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3242 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3244 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3245 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3248 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3250 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3251 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3253 rlsHqBufs->numUes++;
3258 node = sf->ackNakRepQ.first;
3261 tbCb = (RgSchDlHqTbCb *)(node->node);
3264 procId = hqP->procId;
3265 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3266 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3267 if (HQ_TB_WAITING == tbCb->state)
3269 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3270 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3271 timingInfo, isAck[0], rlsHqBufs, err);
3273 hqP->cwSwpEnabled = FALSE;
3274 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3276 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3277 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3279 rlsHqBufs->numUes++;
3286 } /* rgSCHDhmHqFdbkInd */
3287 #endif /* LTE_FDD */
3291 * @brief Handler for Harq related UE configuration.
3295 * Function : rgSCHDhmRgrUeCfg
3297 * This function shall fetch the harq related information into the
3298 * respective ueCb from the UE configuration as provided by the
3301 * @param[in] RgSchCellCb *cell
3302 * @param[in] RgSchUeCb *ueCb
3303 * @param[in] RgrUeCfg *ueCfg
3304 * @param[out] RgSchErrInfo *err
3309 Void rgSCHDhmRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ueCb,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3314 /* Initialize the TA Timer */
3315 cmInitTimers(&ueCb->taTmr, 1);
3317 /* Setting these values irrespective of taTmr value */
3318 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3319 /* Corrected default value of TA as per 36.213, 4.2.3 */
3320 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3322 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3323 ueCb->dl.taCb.outStndngTa = FALSE;
3324 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3326 /* Start TA timer only if cfgd as FINITE value */
3327 if (ueCfg->ueTaTmrCfg.pres)
3329 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3330 * TA command before the expiry of TA at UE. Also considering for
3331 * possible retx for this TA command */
3332 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3333 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3335 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3337 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3340 } /* rgSCHDhmRgrUeCfg */
3344 * @brief Handler for HARQ related UE Reconfiguration
3348 * Function : rgSCHDhmRgrCellCfg
3350 * This function shall fetch the HARQ related information into the
3351 * respective ueCb from the UE configuration as provided by the
3354 * @param[in] RgSchCellCb *cell
3355 * @param[in] RgrCellCfg *cellCfg
3356 * @param[out] RgSchErrInfo *err
3362 Void rgSCHDhmRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3365 PTR pUeCb;/* previous UE Control block */
3366 PTR nUeCb;/* next UE control block */
3374 cell->dlHqCfg = cellCfg->dlHqCfg;
3377 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3385 /* Update the DL Harq related information */
3386 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3387 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3390 /* Initializing the list for ueCbs that would have ta */
3391 cmLListInit(&cell->taUeLst);
3393 cmLListInit(&cell->ccchSduUeLst);
3394 cmLListInit(&cell->contResGrdTmrLst);
3395 cmLListInit(&cell->contResTmrLst);
3397 if(cell->emtcEnable)
3399 rgSCHDhmEmtcRgrCellCfg(cell);
3404 /* Initializing the timer queue */
3405 cell->tqCp.nxtEnt = 0;
3406 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3408 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3410 cell->tq[idx].first = NULLP;
3411 cell->tq[idx].tail = NULLP;
3414 } /* rgSCHDhmRgrCellCfg */
3417 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3421 * Function : rgSCHDhmRgrCellRecfg
3423 * This function shall fetch the HARQ related information into the
3424 * respective ueCb from the UE configuration as provided by the
3427 * @param[in] RgSchCellCb *cell
3428 * @param[in] RgrCellRecfg *cellRecfg
3429 * @param[out] RgSchErrInfo *err
3435 Void rgSCHDhmRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *cellRecfg,RgSchErrInfo *err)
3438 PTR pUeCb;/* previous UE Control block */
3439 PTR nUeCb;/* next UE control block */
3446 /* Update the cell with recieved configuration */
3447 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3449 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3453 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3461 /* Update the DL Harq related information */
3462 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3463 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3468 } /* rgSCHDhmRgrCellRecfg */
3471 * @brief Handler for freeing up the HARQ related information from ueCb
3475 * Function : rgSCHDhmFreeUe
3477 * This function shall free up the HARQ specific information from ueCb.
3479 * @param[in] RgSchUeCb *ueCb
3484 Void rgSCHDhmFreeUe(RgSchUeCb *ueCb)
3487 /* If TA Timer is running. Stop it */
3488 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3490 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3493 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3494 * doesn't expire after UE is deleted */
3496 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3498 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3500 #endif /* ifdef RGR_V1*/
3503 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3505 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3508 /* This UE needs to be removed from its entry into cell's taUeLst */
3509 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3510 if(ueCb->taLnk.node)
3512 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3513 ueCb->taLnk.node = NULLP;
3516 if (ueCb->dlTaLnk.node != NULLP)
3518 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3519 * function directly from other modules. APIs should be defined and/or used
3520 * instead. Please check for other possible incorrect usage. */
3521 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3526 } /* rgSCHDhmFreeUe */
3529 * @brief Handler for updating the TA.
3533 * Function : rgSCHDhmUpdTa
3535 * This function shall update the TA received.
3537 * @param[in] RgSchCellCb *cell
3538 * @param[in] RgSchUeCb *ueCb
3539 * @param[in] uint8_t ta
3544 Void rgSCHDhmUpdTa(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t ta)
3547 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3549 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3550 ueCb->dl.taCb.numRemSf = 2;
3551 rgSCHUtlDlTARpt(cell, ueCb);
3552 /* If TA Timer is running. Stop it */
3553 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3555 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3558 /* SR_RACH_STATS : TA MODIFIED */
3559 if (ueCb->dl.taCb.ta != ta)
3563 ueCb->dl.taCb.ta = ta;
3567 /* [ccpu00121813]-ADD-Updating outstanding values
3568 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3569 * has been scheduled,further TA values get stored in outstndngTaval.
3570 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3571 * then schedule the outstanding TA val if present */
3572 ueCb->dl.taCb.outStndngTa = TRUE;
3573 ueCb->dl.taCb.outStndngTaval = ta;
3577 } /* rgSCHDhmUpdTa */
3579 /** @brief This function handles the TA timer expiry.
3583 * Function: This function handled the TA Expiry.
3589 * @param[in] RgSchUeCb *ueCb
3594 Void rgSCHDhmProcTAExp( RgSchUeCb *ueCb)
3596 /* Ask scheduler to schedule this UE */
3597 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3598 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
3600 } /* end of rgSCHDhmProcTAExp */
3602 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
3604 * @brief Handler for Adding scheduled logical channel data information
3609 * Function : rgSCHDhmAddLcData
3611 * This function shall add the scheduled logical channel data
3612 * information to the HARQ process.
3614 * @param[in] RgSchLchAllocInfo *lchData
3615 * @param[in] RgSchDlHqTbCb *tbInfo
3620 S16 rgSCHDhmAddLcData(Inst inst,RgSchLchAllocInfo *lchData,RgSchDlHqTbCb *tbInfo)
3623 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
3628 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
3634 } /* rgSCHDhmAddLcData */
3638 * @brief Handler for releaseing the subframe allocation.
3642 * Function : rgSCHDhmTddRlsSubFrm
3644 * This function shall be invoked to release the DL Sf
3645 * allocations for which HARQ feedback time has expired.
3647 * @param[in] RgSchCellCb *cellCb
3648 * @param[in] CmLteTimingInfo uciTimingInfo;
3653 S16 rgSCHDhmTddRlsSubFrm(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3655 CmLteTimingInfo dlSfTime;
3656 RgSchTddDlAscSetIdxK ascIdx;
3661 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3662 noFdbks = ascIdx.numFdbkSubfrms;
3663 for(i=0; i < noFdbks; i++)
3665 /* Get the subframe and sfn for which HARQ Ack/Nack
3667 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3668 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3669 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3670 * as it is serving the purpose */
3671 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3672 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
3675 }/* rgSCHDhmTddRlsSubFrm */
3678 uint32_t macDtx = 0;
3681 * @brief Handler for Removing the HARQ process from a dlsf.
3685 * Function : rgSCHDhmRlsDlsfHqProc
3687 * This function shall be invoked for every tti. It goes back to
3688 * to the sixth last subframe to check whether it still exists. If
3689 * that exists this function traverses through the entire harq
3690 * proc list associated and frees up all of them.
3692 * @param[in] RgSchCellCb *cellCb
3693 * @param[in] CmLteTimingInfo timingInfo
3698 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cellCb,CmLteTimingInfo uciTimingInfo)
3701 CmLteTimingInfo dlSfTime;
3702 CmLteTimingInfo nxtfrm = {0,0};
3703 RgSchDlHqProcCb *tmpHqProc;
3704 RgSchTddDlAscSetIdxK ascIdx;
3707 RgSchDlSf *nxtDlsf = NULLP;
3711 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
3712 uint8_t maxRetx=FALSE;
3713 RgSchTddANInfo *anInfo = NULLP;
3714 RgSchDlHqTbCb *tbCb;
3715 RgSchUeCb *ue = NULLP;
3718 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.slot];
3719 noFdbks = ascIdx.numFdbkSubfrms;
3720 for(i=0; i < noFdbks; i++)
3722 /* Get the subframe and sfn for which HARQ Ack/Nack
3724 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
3725 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3726 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3727 * as it is serving the purpose */
3728 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
3730 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
3731 if(cellCb->ulDlCfgIdx != 5)
3733 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
3735 /* Subframe is present. Delete all the harq associations from
3739 /*Handling for Msg4*/
3740 node = dlSf->msg4HqPLst.first;
3743 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
3745 tmpHqProc->cwSwpEnabled = FALSE;
3746 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
3748 tbCb = &tmpHqProc->tbInfo[0];
3750 /* Fix : syed MultiUe per TTI crash in TA List. */
3754 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3757 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3759 /* Delete the Harq Association. Release the Harq Process */
3760 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3762 if (tbCb->taSnt == TRUE)
3764 /* [ccpu00127148] Correcting the check */
3765 if (TRUE == maxRetx)
3767 tbCb->taSnt = FALSE;
3768 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3769 ue->dl.taCb.state = RGSCH_TA_IDLE;
3771 rgSCHUtlReTxTa(cellCb, ue);
3777 node = dlSf->ueLst.first;
3783 ue = (RgSchUeCb *)(node->node);
3787 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
3790 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
3791 hqPNode = hqPNode->next;
3792 for (idx = 0 ;idx < 2; idx++)
3794 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
3796 tbCb = &tmpHqProc->tbInfo[idx];
3798 /* Fix : syed MultiUe per TTI crash in TA List. */
3802 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3805 /* Update feedback time for this process so that
3806 * next subframe its picked up */
3808 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3809 tmpHqProc->hqE->cell->instIdx,
3810 tmpHqProc->hqE->cell->cellId,
3812 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3814 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
3818 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
3819 "Ack/Nack Info is NULL, Processing %dth feedback slot for DTX"
3820 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
3821 uciTimingInfo.slot));
3823 else if (tbCb->fbkRepCntr == 0)
3825 /* Initialise the Ack/Nack feedback */
3827 if(!(anInfo->dlDai))
3829 rgSCHUtlInitUeANFdbkInfo(anInfo);
3834 /* Update feedback time for this process so that
3835 * * next subframe its picked up */
3836 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3837 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3838 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3839 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
3844 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
3845 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
3848 /* Delete the Harq Association. Release the Harq Process */
3849 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3851 if (tbCb->taSnt == TRUE)
3853 /* [ccpu00127148] Correcting the check */
3854 if (TRUE == maxRetx)
3856 tbCb->taSnt = FALSE;
3857 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
3858 ue->dl.taCb.state = RGSCH_TA_IDLE;
3860 rgSCHUtlReTxTa(cellCb, ue);
3862 DU_LOG("\nDEBUG --> SCH : Nack/DTX Rcvd for TA. Max Tries Attempted");
3871 node = dlSf->ackNakRepQ.first;
3874 tbCb = (RgSchDlHqTbCb *)(node->node);
3875 tmpHqProc = tbCb->hqP;
3876 /* [ccpu00121813]-ADD-Fetch ueCb */
3877 ue = tmpHqProc->hqE->ue;
3878 /* Fix : syed MultiUe per TTI crash in TA List. */
3883 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
3884 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
3888 /* If This is not the last repetition */
3889 if (tbCb->fbkRepCntr > 1)
3891 /* Update feedback time for this process so that
3892 * next subframe its picked up */
3894 uint8_t servCellIdx = rgSchUtlGetServCellIdx(
3895 tmpHqProc->hqE->cell->instIdx,
3896 tmpHqProc->hqE->cell->cellId,
3898 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
3900 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
3906 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
3907 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
3908 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
3909 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3915 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
3917 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
3919 /*even if one NACK, we consider the feedback
3920 * on a whole as NACk */
3921 if ( tbCb->nackCount != 0 )
3923 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
3927 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
3931 /* Delete the Harq Association. Release the Harq Process */
3932 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
3934 }/*if(((tbCb->nackCount+....*/
3937 if (tbCb->taSnt == TRUE)
3939 /* [ccpu00127148] Correcting the check */
3940 if (TRUE == maxRetx)
3942 tbCb->taSnt = FALSE;
3943 ue->dl.taCb.state = RGSCH_TA_IDLE;
3945 rgSCHUtlReTxTa(cellCb, ue);
3946 DU_LOG("\nDEBUG --> SCH : Nack/DTX Rcvd for TA. Max Tries Attempted");
3953 }/* rgSCHDhmRlsDlsfHqProc */
3954 #else /* ifdef LTE_TDD */
3956 * @brief Handler for Removing the HARQ process from a dlsf.
3960 * Function : rgSCHDhmRlsDlsfHqProc
3962 * This function shall be invoked for every tti. It goes back to
3963 * to the sixth last subframe to check whether it still exists. If
3964 * that exists this function traverses through the entire harq
3965 * proc list associated and frees up all of them.
3967 * @param[in] RgSchCellCb *cell
3972 S16 rgSCHDhmRlsDlsfHqProc(RgSchCellCb *cell,CmLteTimingInfo timingInfo)
3975 CmLteTimingInfo frm;
3976 RgSchDlHqProcCb *tmpHqProc;
3981 RgSchDlHqTbCb *tbCb;
3984 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
3985 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
3986 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
3987 * as it is serving the purpose */
3988 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
3991 /* Get the required Last subframe */
3992 sf = rgSCHUtlSubFrmGet(cell, frm);
3995 /*Handling for Msg4*/
3996 node = sf->msg4HqPLst.first;
3999 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4000 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4002 tbCb = &tmpHqProc->tbInfo[0];
4003 /* Fix : syed MultiUe per TTI crash in TA List. */
4006 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4007 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4010 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4011 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4013 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4018 if (tbCb->fbkRepCntr != 0)
4020 /* Update timingInfo for this hqP so that next subframe its picked up */
4021 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4022 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4026 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4028 /* Delete the Harq Association. Release the Harq Process */
4029 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4033 /* Subframe is present. Delete all the harq associations from
4036 node = sf->ueLst.first;
4039 ue = (RgSchUeCb *)(node->node);
4043 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4047 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4048 tmpHqProc->cwSwpEnabled = FALSE;
4049 hqPNode = hqPNode->next;
4050 for (idx = 0 ;idx < 2; idx++)
4052 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4054 tbCb = &tmpHqProc->tbInfo[idx];
4055 /* Fix : syed MultiUe per TTI crash in TA List. */
4058 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4059 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4062 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4063 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4065 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4070 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4073 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4076 /* Delete the Harq Association. Release the Harq Process */
4077 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4079 if (tbCb->taSnt == TRUE)
4081 /* [ccpu00127148] Correcting the check */
4082 if (TRUE == maxRetx)
4084 tbCb->taSnt = FALSE;
4085 ue->dl.taCb.state = RGSCH_TA_IDLE;
4087 rgSCHUtlReTxTa(cell, ue);
4088 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4089 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4092 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4093 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4102 } /* rgSCHDhmRlsDlsfHqProc */
4107 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4112 * Function: rgSCHDhmMarkSpsHqProc
4113 * Purpose: This function returns the HARQ process with the given ID.
4114 * Invoked by: SPS Module
4116 * - Get the HARQ process by index from the UE
4117 * - Set isSpsHqProc = TRUE
4119 * @param[in] RgSchUeCb *ue
4120 * @param[in] uint8_t idx
4122 * -# ROK if successful
4123 * -# RFAILED otherwise
4126 S16 rgSCHDhmMarkSpsHqProc(RgSchUeCb *ue,uint8_t idx)
4128 RgSchDlHqProcCb *hqP;
4130 /* Pick the proc based on the index provided */
4131 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4134 } /* rgSCHDhmMarkSpsHqProc */
4135 #endif /* RG_UNUSED */
4136 #endif /* LTEMAC_SPS */
4139 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4143 * Function : rgSCHDhmProcHqFdbkAckNackRep
4145 * This function shall act on the feedback received from TOM for DL
4149 * @param[in] RgSchDlHqProcCb *hqP
4150 * @param[in] RgSchDlSf *sf
4151 * @param[in] uint8_t tbCnt
4152 * @param[in] uint8_t *isAck
4157 static S16 rgSCHDhmProcHqFdbkAckNackRep(RgSchDlHqProcCb *hqP,RgSchDlSf *sf,uint8_t tbCnt,uint8_t *isAck)
4159 /* Check if this is repeating UE */
4160 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4161 /* Check if last repetition */
4162 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4164 /* Update timingInfo for this hqP so that next subframe its picked up */
4165 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4166 hqP->tbInfo[tbCnt].timingInfo, 1);
4170 /* Take decision here based on the number
4171 * of DTX's,NACK's and ACK's received
4173 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4174 (hqP->tbInfo[tbCnt].dtxCount)))
4176 *isAck = TFU_HQFDB_ACK;
4178 /*even a single NACK indicates that UE received
4181 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4183 *isAck = TFU_HQFDB_NACK;
4187 *isAck = TFU_HQFDB_DTX;
4191 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4194 #endif /* ifndef LTE_TDD */
4197 /* Freeing up the HARQ proc blocked for
4198 * indefinite time in case of Retx */
4200 * @brief This function handles the scenario in case Retx allocation is failed.
4204 * Function: rgSCHDhmDlRetxAllocFail
4207 * @param[in] RgSchUeCb *ue
4208 * @param[in] RgSchDlHqProcCb *hqP
4212 S16 rgSCHDhmDlRetxAllocFail(RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
4215 RgInfRlsHqInfo *rlsHqInfo;
4217 Bool maxRetx = FALSE;
4218 RgSchCmnCell *cellSch;
4220 cell = hqP->hqE->cell;
4221 cellSch = RG_SCH_CMN_GET_CELL(cell);
4222 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4224 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4225 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4227 hqP->tbInfo[0].cntrRetxAllocFail++;
4230 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4231 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4233 hqP->tbInfo[1].cntrRetxAllocFail++;
4236 /* initialize MAC-SCH interface HARQ release info */
4237 rlsHqInfo->numUes = 0;
4238 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4240 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4241 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4243 if (hqP->hqE->msg4Proc == hqP)
4245 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4249 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4252 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4257 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4258 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4262 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4263 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4266 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4267 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4270 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4271 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4272 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4275 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4276 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4278 if (hqP->hqE->msg4Proc == hqP)
4280 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4284 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4287 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4289 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4290 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4291 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4292 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4293 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4296 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4298 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4299 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4301 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4304 /* send HARQ release to MAC */
4305 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4307 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4308 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4309 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4310 rlsHqInfo->numUes = 1;
4312 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4313 RgSchMacRlsHq(&pst, rlsHqInfo);
4320 static S16 rgSCHDhmUpdateAckNackHistory(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t hqfdbk,uint8_t tbCnt)
4324 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4327 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4330 if (hqfdbk == TFU_HQFDB_ACK)
4332 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4336 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4339 printf("\nDEBUG --> SCH: deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4340 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4341 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4344 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4349 S16 rgSCHDhmUpdBlerBasediTbsEff(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t tbCnt)
4353 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4354 uint8_t cfi = cellSch->dl.currCfi;
4355 uint8_t maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4356 maxiTbs = RG_SCH_DL_MAX_ITBS;
4358 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4359 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4363 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4364 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4368 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4369 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4373 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4374 ueDl->laCb[tbCnt].deltaiTbs)/100),
4375 ueCb->cell->thresholds.maxDlItbs);
4378 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4380 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4382 /* Eff for CW for 1 Layer Tx */
4383 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4384 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4385 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4387 /* Eff for CW for 2 Layer Tx */
4388 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4389 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4390 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4398 * @brief This function Processes the Hq Fdbk in case of
4399 * special Bundling in TDD (FAPIv1.1: Table 79)
4403 * Function: rgSCHDhmPrcSplBundlFdbk
4404 * Purpose: To Interpret the Harq Feedback according to
4405 * table 7.3-1: 36.213
4407 * 0 = 0 or None (UE detect at least one DL is missed)
4408 * 1 = 1 or 4 or 7 ACKs reported
4409 * 2 = 2 or 5 or 8 ACKs reported
4410 * 3 = 3 or 6 or 9 ACKs reported
4411 * 4 = DTX (UE did not transmit anything)
4413 * @param[in] TfuHqInfo *fdbk
4414 * @param[in] uint8_t hqCnt
4418 static Void rgSCHDhmPrcSplBundlFdbk(RgSchCellCb *cell,TfuHqInfo *fdbk,uint8_t hqCnt)
4422 /* Num of ACKs reported by UE */
4423 numOfAcks = fdbk->isAck[0];
4425 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4426 fdbk->isAck[0] == TFU_HQFDB_DTX)
4432 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4433 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4435 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4438 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4439 the PDSCH trasnmission (spatial bundling). So we have
4440 to assume same feedback for both codewords */
4442 for(uint8_t idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
4444 fdbk->isAck[idx] = fdbk->isAck[0];
4447 fdbk->isAck[1] = fdbk->isAck[0];
4455 * @brief This function adds HARQ process to FREE list
4459 * Function: rgSCHDhmHqPAdd2FreeLst
4462 * Invoked by: scheduler
4464 * @param[out] RgDlHqProc *hqP
4468 Void rgSCHDhmHqPAdd2FreeLst(RgSchDlHqProcCb *hqP)
4475 printf("\nDEBUG --> SCH: Crashing already part of free lst\n");
4476 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4480 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
4481 hqP->hqPLst = &hqP->hqE->free;
4485 if (hqP->hqE->free.count > 8)
4488 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4489 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4495 rgSCHLaaHndlHqProcFree(hqP);
4499 } /* rgSCHDhmHqPAdd2FreeLst */
4503 * @brief This function adds HARQ process to inUse list
4507 * Function: rgSCHDhmHqPAdd2InUseLst
4510 * Invoked by: scheduler
4512 * @param[out] RgDlHqProc *hqP
4516 Void rgSCHDhmHqPAdd2InUseLst(RgSchDlHqProcCb *hqP)
4523 printf("\nDEBUG --> SCH: Crashing already part of inuse lst\n");
4524 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4528 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
4529 hqP->hqPLst = &hqP->hqE->inUse;
4533 if (hqP->hqE->inUse.count > 8)
4536 printf("\nDEBUG --> SCH: Crashing invalid hq count \n");
4537 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4543 } /* rgSCHDhmHqPAdd2InUseLst */
4546 * @brief This function adds HARQ process to FREE list
4550 * Function: rgSCHDhmHqPDelFrmFreeLst
4553 * Invoked by: scheduler
4555 * @param[out] RgDlHqProc *hqP
4559 Void rgSCHDhmHqPDelFrmFreeLst(RgSchDlHqProcCb *hqP)
4566 printf("\nDEBUG --> SCH: Crashing not part of any lst\n");
4567 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4572 if (hqP->hqPLst != &hqP->hqE->free)
4575 printf("\nDEBUG --> SCH: Crashing del from wrong lst\n");
4576 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4581 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
4582 hqP->hqPLst = NULLP;
4585 if (hqP->hqE->free.count > 8)
4588 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4589 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4595 } /* rgSCHDhmHqPDelFrmFreeLst */
4600 * @brief This function adds HARQ process to FREE list
4604 * Function: rgSCHDhmHqPDelFrmInUseLst
4607 * Invoked by: scheduler
4609 * @param[out] RgDlHqProc *hqP
4613 Void rgSCHDhmHqPDelFrmInUseLst(RgSchDlHqProcCb *hqP)
4620 printf("\nDEBUG --> SCH: Crashing not part of any lst\n");
4621 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4627 if (hqP->hqPLst != &hqP->hqE->inUse)
4630 printf("\nDEBUG --> SCH: Crashing del from wrong lst\n");
4631 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4636 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
4637 hqP->hqPLst = NULLP;
4640 if (hqP->hqE->inUse.count > 8)
4643 printf("\nDEBUG --> SCH: Crashing invalid hq count\n");
4644 printf("\nDEBUG --> SCH: Crashing %d \n", *p);
4650 } /* rgSCHDhmHqPDelFrmInUseLst */
4653 /**********************************************************************
4656 **********************************************************************/