1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions
29 **********************************************************************/
31 /** @file rg_sch_dhm.c
32 @brief APIs related to Downlink HARQ for the scheduler.
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_FILE_ID=242;
37 static int RLOG_MODULE_ID=4096;
39 /* header include files -- defines (.h) */
40 #include "envopt.h" /* environment options */
41 #include "envdep.h" /* environment dependent */
42 #include "envind.h" /* environment independent */
43 #include "gen.h" /* general layer */
44 #include "ssi.h" /* system service interface */
45 #include "cm5.h" /* common timers */
46 #include "cm_hash.h" /* common hash list */
47 #include "cm_mblk.h" /* common memory link list library */
48 #include "cm_llist.h" /* common linked list library */
49 #include "cm_err.h" /* common error */
50 #include "cm_lte.h" /* common LTE */
56 #include "rg_sch_err.h"
57 #include "rg_sch_inf.h" /* typedefs for Scheduler */
59 #include "rg_sch_cmn.h"
60 #include "rl_interface.h"
61 #include "rl_common.h"
63 /* header/extern include files (.x) */
64 #include "gen.x" /* general layer */
65 #include "ssi.x" /* system service interface */
66 #include "cm5.x" /* common timers */
67 #include "cm_lib.x" /* common library */
68 #include "cm_hash.x" /* common hash list */
69 #include "cm_llist.x" /* common linked list library */
70 #include "cm_mblk.x" /* memory management */
71 #include "cm_tkns.x" /* common tokens */
72 #include "cm_lte.x" /* common LTE */
77 #include "rg_sch_inf.x" /* typedefs for Scheduler */
79 #include "rg_sch_cmn.x"
81 #ifdef RGSCH_SPS_STATS
82 extern U32 rgNumSPSSchedDropMaxRetx;
83 extern U32 rgNumActDtx;
85 PUBLIC U32 nackSf[10];
90 PUBLIC RgSchNackAckStats hqFailStats;
91 PUBLIC RgSchHqRetxStats hqRetxStats;
92 #endif /* MAC_SCH_STATS */
93 //Chandan Stats Collection
96 RgSchDlHqStats dlHqStats[10000] = {{0,0,0}};
100 /* For special bundling case: convert numOfAcks to ACK/NACK
101 * The below table derives the HARQ aknowledgement as ACK or NACK using the
102 * number of transmission done and the feedback value received
103 * The below table is based on Table 7.3-X from 36.213 and
104 * table 79 from FAPIv1.1 doc
106 U8 rgSchNumOfAcksToAckNack[RG_SCH_MAX_NUM_EXPECTED_ACKS][RG_SCH_NUM_FDBK_VALUE] = {
107 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
108 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
109 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
110 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
111 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
112 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK},
113 {TFU_HQFDB_ACK, TFU_HQFDB_NACK, TFU_HQFDB_NACK},
114 {TFU_HQFDB_NACK, TFU_HQFDB_ACK, TFU_HQFDB_NACK},
115 {TFU_HQFDB_NACK, TFU_HQFDB_NACK, TFU_HQFDB_ACK}
123 PRIVATE Void rgSCHDhmFdbkIndHndlTa ARGS((RgSchDlHqProcCb *hqP, U8 tbIdx, U8 fdbk,
124 Bool maxHqRetxReached));
125 PUBLIC void rgEmtcsetNullSubFrm ARGS((RgSchDlHqProcCb *hqP));
127 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep ARGS((
128 RgSchDlHqProcCb *hqP,
135 PRIVATE S16 rgSCHDhmUpdateAckNackHistory ARGS((
143 PRIVATE Void rgSCHDhmPrcSplBundlFdbk ARGS((
149 PRIVATE Void rgSchGetHqFdbkPosForM1 ARGS((
151 RgSchDlHqProcCb *hqP,
155 RgSchTddANInfo *anInfo
157 PRIVATE Void rgSchGetHqFdbkPosForM234 ARGS((
159 RgSchDlHqProcCb *hqP,
163 RgSchTddANInfo *anInfo,
165 CmLteTimingInfo timeInfo
170 /* Freeing up the HARQ proc blocked for
171 * indefinite time in case of Retx */
172 PUBLIC S16 rgSCHDhmDlRetxAllocFail ARGS((
174 RgSchDlHqProcCb *proc
178 EXTERN S16 rgSCHDhmEmtcRgrCellCfg ARGS((
184 extern U32 gPCellTb1AckCount,gPCellTb2AckCount,gPCellTb1NackCount,gPCellTb2NackCount;
185 extern U32 gSCellSchedCount,gPrimarySchedCount;
186 extern U32 gSCellTb1AckCount,gSCellTb2AckCount,gSCellTb1NackCount,gSCellTb2NackCount;
187 extern U32 gPCellTb1DtxCount, gPCellTb2DtxCount, gSCellTb1DtxCount, gSCellTb2DtxCount;
188 extern U32 gHqFdbkCount;
192 EXTERN Void rgSCHEmtcUtlDlHqPTbRmvFrmTx
194 RgSchEmtcDlSf *subFrm,
195 RgSchDlHqProcCb *hqP,
199 EXTERN RgSchEmtcDlSf* rgSCHEmtcUtlSubFrmGet
204 EXTERN Void rgSCHEmtcHqInfoAlloc ARGS((RgSchCellCb *cell, RgSchDlHqProcCb *hqP));
206 /* forward references */
209 * @brief This function initializes the DL HARQ Entity of UE.
213 * Function: rgSCHDhmHqEntInit
214 * Purpose: This function initializes the DL HARQ entity of
215 * UE control block. This is performed at the time
216 * of creating UE control block.
218 * Invoked by: configuration module
220 * @param[in] RgSchCellCb* cell
221 * @return RgSchDlHqEnt *
224 /*MS_WORKAROUND for ccpu00122893*/
226 PUBLIC Void rgSCHDhmHqEntReset
231 PUBLIC Void rgSCHDhmHqEntReset(hqE)
235 RgSchDlHqProcCb *hqP;
237 TRC2(rgSCHDhmHqEntReset)
238 cmLListInit(&hqE->inUse);
239 cmLListInit(&hqE->free);
240 for (i=0; i < hqE->numHqPrcs; i++)
242 hqP = &hqE->procs[i];
245 /* Fix - reset numLch */
246 hqP->tbInfo[0].numLch = 0;
247 hqP->tbInfo[1].numLch = 0;
248 hqP->tbInfo[0].txCntr = 0;
249 hqP->tbInfo[0].ndi = 0; /* Initialize the NDI to Zero */
250 hqP->tbInfo[1].txCntr = 0;
251 hqP->tbInfo[1].ndi = 0; /* Initialize the NDI to Zero */
252 hqP->tbInfo[0].tbIdx = 0;
253 hqP->tbInfo[1].tbIdx = 1;
254 hqP->tbInfo[0].hqP = hqP;
255 hqP->tbInfo[1].hqP = hqP;
256 hqP->tbInfo[0].state = HQ_TB_ACKED;
257 hqP->tbInfo[1].state = HQ_TB_ACKED;
258 hqP->tbInfo[0].contResCe = NOTPRSNT;
259 hqP->tbInfo[1].contResCe = NOTPRSNT;
260 hqP->lnk.node = (PTR)hqP;
261 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
263 rgSCHDhmHqPAdd2FreeLst(hqP);
264 hqP->tbInfo[0].lchSchdData = hqP->tbInfo[0].lchSchdDataArr;
265 hqP->tbInfo[1].lchSchdData = hqP->tbInfo[1].lchSchdDataArr;
266 hqP->drxCb.rttIndx = DRX_INVALID;
267 hqP->drxCb.reTxIndx = DRX_INVALID;
268 hqP->tbInfo[0].cntrRetxAllocFail = 0;
269 hqP->tbInfo[1].cntrRetxAllocFail = 0;
270 hqP->hasDcch = FALSE;
271 hqP->cwSwpEnabled = FALSE;
276 rgSCHLaaResetDlHqProcCb(hqP);
280 } /* rgSCHDhmHqEntReset */
283 * @brief This function assigns dlHqEnt of raCb to ueCb.
287 * Function: rgSCHDhmAssgnUeHqEntFrmRaCb
288 * Purpose: This function assigns dlHqEnt of raCb to ueCb.
290 * Invoked by: configuration module
292 * @param[in] RgSchUeCb *ue
293 * @param[in] RgSchRaCb *raCb
298 PUBLIC Void rgSCHDhmAssgnUeHqEntFrmRaCb
304 PUBLIC Void rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb)
309 TRC2(rgSCHDhmAssgnUeHqEntFrmRaCb)
311 ue->cellInfo[0]->hqEnt = raCb->dlHqE;
312 ue->cellInfo[0]->hqEnt->ue = ue;
313 /* Update the DL Harq related information */
314 ue->cellInfo[0]->hqEnt->maxHqTx = ue->cell->dlHqCfg.maxDlHqTx;
316 /* Fix : set UE active in DL as UE initialization completed */
317 ue->dl.dlInactvMask &= ~(RG_HQENT_INACTIVE);
318 ue->ul.ulInactvMask &= ~(RG_HQENT_INACTIVE);
319 rgSCHCmnDlInitHqEnt(ue->cell, ue->cellInfo[0]->hqEnt);
325 * @brief This function deletes the dlHqEnt.
329 * Function: rgSCHDhmDelHqEnt
330 * Purpose: This function deletes the dlHqEnt.
332 * Invoked by: configuration module
334 * @param[in] RgSchCellCb *cell
335 * @param[in] RgSchDlHqEnt **hqE
340 PUBLIC Void rgSCHDhmDelHqEnt
346 PUBLIC Void rgSCHDhmDelHqEnt(cell, hqE)
351 TRC2(rgSCHDhmDelHqEnt)
358 rgSCHCmnDlDeInitHqEnt(cell, *hqE);
360 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)hqE,
361 sizeof(RgSchDlHqEnt));
367 PUBLIC RgSchDlHqEnt *rgSCHDhmHqEntInit
372 PUBLIC RgSchDlHqEnt *rgSCHDhmHqEntInit(cell)
377 Inst inst = cell->instIdx;
379 TRC2(rgSCHDhmHqEntInit)
381 /* Init the HARQ data structure */
382 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE, sizeof(RgSchDlHqEnt)) != ROK)
384 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
385 "rgSCHDhmHqEntInit hqE alloc fail");
389 /* Init the HARQ processes */
390 hqE->numHqPrcs = rgSchTddDlNumHarqProcTbl[cell->ulDlCfgIdx];
391 if (rgSCHUtlAllocSBuf(inst, (Data **)&hqE->procs,
392 hqE->numHqPrcs * sizeof(RgSchDlHqProcCb)) != ROK)
394 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
395 "rgSCHDhmHqEntInit hqP alloc fail in hqE");
399 hqE->numHqPrcs = RGSCH_NUM_DL_HQ_PROC;
403 rgSCHLaaInitDlHqProcCb (cell, hqE);
406 /* Initialize maximum tranmission counter */
407 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
410 /* MW_WORKAROUND for ccpu00122893 */
411 rgSCHDhmHqEntReset(hqE);
417 } /* rgSCHDhmHqEntInit */
420 * @brief This function gets an available HARQ process.
424 * Function: rgSCHDhmGetAvlHqProc
425 * Purpose: This function returns an available HARQ process in
426 * the DL direction. All HARQ processes are maintained
427 * in queues of free and inuse.
429 * 1. Check if the free queue is empty. If yes, return
431 * 2. If not empty, update the proc variable with the
432 * first process in the queue. Return ROK.
434 * Invoked by: scheduler
436 * @param[in] RgSchUeCb *ue
437 * @param[in] CmLteTimingInfo timingInfo
438 * @param[out] RgSchDlHqProc **hqP
440 * -#ROK if successful
441 * -#RFAILED otherwise
445 PUBLIC S16 rgSCHDhmGetAvlHqProc
449 CmLteTimingInfo timingInfo,
450 RgSchDlHqProcCb **hqP
453 PUBLIC S16 rgSCHDhmGetAvlHqProc (cell, ue, timingInfo, hqP)
456 CmLteTimingInfo timingInfo;
457 RgSchDlHqProcCb **hqP;
460 RgSchDlHqEnt *hqE = NULLP;
461 RgSchDlHqProcCb *tmpHqProc;
463 TRC2(rgSCHDhmGetAvlHqProc);
465 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
469 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHDhmGetAvlHqProc hqE NULL ue %d"
475 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
479 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
480 "rgSCHDhmGetAvlHqProc free %ld inUse %ld ue %d"
481 , hqE->free.count, hqE->inUse.count, ue->ueId);
482 /* No Harq Process available in the free queue. */
486 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
489 /* If SPS HARQ procs are in use, do not use SPS harq procs for non-SPS
491 if (ue->dl.isSpsHqPInUse)
493 while (tmpHqProc->procId < ue->dl.dlSpsCfg.numSpsHqProc)
495 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
500 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
504 /* No Harq Process available in the free queue. */
511 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
512 tmpHqProc->tbInfo[1].timingInfo = timingInfo;
513 tmpHqProc->hasDcch = FALSE;
514 tmpHqProc->cwSwpEnabled = FALSE;
516 /* Remove the element from the free Queue */
517 //cmLListDelFrm(&hqE->free, tmp);
518 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
520 /* Add the element into the inUse Queue as well */
521 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
522 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
527 rgSCHLaaResetDlHqProcCb(tmpHqProc);
531 tmpHqProc->tbSizeAtEstimate[0] = 0;
532 tmpHqProc->tbSizeAtEstimate[1] = 0;
533 tmpHqProc->tbSizeAtFnlz[0] = 0;
534 tmpHqProc->tbSizeAtFnlz[1] = 0;
535 tmpHqProc->tbSizeOfMvdTb[0] = 0;
536 tmpHqProc->tbSizeOfMvdTb[1] = 0;
537 tmpHqProc->itbsAtEstimate[0] = 0;
538 tmpHqProc->itbsAtEstimate[1] = 0;
539 tmpHqProc->prbAtEstimate = 0;
542 } /* rgSCHDhmGetAvlHqProc */
546 * @brief This function adds HARQ process for a given TB in to
547 * the inuse queue upon retx.
551 * Function: rgSCHDhmHqTbRetx
552 * Purpose: This function handles when a HARQ process is scheduled
553 * for retransmission. It adds the HARQ procss to inuse
555 * 1. Check if this HqP is already added to the inUse
556 * queue as part of this function call for other
557 * TB's retransmission.
558 * 2. If already present in inUse Q then do not add.
560 * Invoked by: scheduler
562 * @param[in] RgSchDlHqEnt *hqE
563 * @param[in] CmLteTimingInfo timingInfo
564 * @param[out] RgDlHqProc *hqP
565 * @param[in] U8 tbIdx
570 PUBLIC Void rgSCHDhmHqTbRetx
573 CmLteTimingInfo timingInfo,
574 RgSchDlHqProcCb *hqP,
578 PUBLIC Void rgSCHDhmHqTbRetx(hqE, timingInfo, hqP, tbIdx)
580 CmLteTimingInfo timingInfo;
581 RgSchDlHqProcCb *hqP;
585 U8 othrTbIdx = tbIdx ^ 1;
586 TRC2(rgSCHDhmHqTbRetx)
588 hqP->tbInfo[tbIdx].timingInfo = timingInfo;
590 if (hqE->msg4Proc == hqP)
594 /* fix for ccpu00118633 No Hq proc Avl end*/
596 /* Extra:check if Harq process is already linked to in-use
597 Queue by means of other TB handling. */
598 if (hqP->tbInfo[othrTbIdx].state != HQ_TB_WAITING)
601 if (hqE->msg4Proc != hqP)
603 //cmLListAdd2Tail(&hqE->inUse, &hqP->lnk);
604 rgSCHDhmHqPAdd2InUseLst(hqP);
608 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
611 } /* rgSCHDhmHqTbRetx */
614 * @brief This function returns last scheduled HARQ process for
615 * a UE's HARQ entity.
619 * Function: rgSCHDhmLastSchedHqProc
620 * Purpose: This function returns the last (most recent)
621 * process in the inUse list, which corresponds
622 * to the last scheduled process. Returns NULLP
624 * The reason for introducing this is to have
625 * an ability to check if UE was scheduled
626 * in the current subframe (scheduling would
627 * have caused a proc to be added to the end
628 * of the list, and checking time (only subframe
629 * number probably works) would confirm this.
631 * Invoked by: scheduler
633 * @param[in] RgSchDlHqEnt *hqE
634 * @return RgSchDlHqProcCb *
638 PUBLIC RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc
643 PUBLIC RgSchDlHqProcCb * rgSCHDhmLastSchedHqProc(hqE)
647 TRC2(rgSCHDhmLastSchedHqProc);
648 /* GRPPWR_CNTRL Fix: UE context will not hold a valid hqE,
649 * until RACH procedure is completed */
650 if ((hqE == NULLP) || (hqE->inUse.last == NULLP))
654 RETVALUE((RgSchDlHqProcCb *)hqE->inUse.last->node);
655 } /* rgSCHDhmLastSchedHqProc */
659 * @brief This function gets an available HARQ process for MSG 4.
663 * Function: rgSCHDhmGetCcchSduHqProc
664 * Purpose: This function returns an available HARQ process in
665 * the DL direction. All HARQ processes are maintained
666 * in queues of free and inuse.
668 * 1. Check if the free queue is empty. If yes, return
670 * 2. If not empty, update the proc variable with the
671 * first process in the queue. Return ROK.
673 * Invoked by: scheduler
675 * @param[in] RgSchRaCb *raCb
676 * @param[in] CmLteTimingInfo timingInfo
677 * @param[out] RgSchDlHqProcCb **hqP
679 * -#ROK if successful
680 * -#RFAILED otherwise
684 PUBLIC S16 rgSCHDhmGetCcchSduHqProc
687 CmLteTimingInfo timingInfo,
688 RgSchDlHqProcCb **hqP
691 PUBLIC S16 rgSCHDhmGetCcchSduHqProc (ueCb, timingInfo, hqP)
693 CmLteTimingInfo timingInfo;
694 RgSchDlHqProcCb **hqP;
697 RgSchDlHqProcCb *tmpHqProc;
701 TRC2(rgSCHDhmGetCcchSduHqProc)
703 hqE = ueCb->cellInfo[0]->hqEnt;
704 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
707 /* No Harq Process available in the free queue. */
711 /* Remove the element from the free Queue and */
712 /* set the MSG 4 HARQ proc pointer */
713 //cmLListDelFrm(&hqE->free, tmp);
715 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
717 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
719 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
720 /* Fix : syed minor code reorg */
722 /*Updating ccchSduProc to identify feedback for CCCH SDU sent without
724 hqE->ccchSduProc = tmpHqProc;
725 //cmLListAdd2Tail(&hqE->inUse, &tmpHqProc->lnk);
726 rgSCHDhmHqPAdd2InUseLst(tmpHqProc);
729 } /* rgSCHDhmGetCcchSduHqProc */
733 * @brief This function gets an available HARQ process for MSG 4.
737 * Function: rgSCHDhmGetMsg4HqProc
738 * Purpose: This function returns an available HARQ process in
739 * the DL direction. All HARQ processes are maintained
740 * in queues of free and inuse.
742 * 1. Check if the free queue is empty. If yes, return
744 * 2. If not empty, update the proc variable with the
745 * first process in the queue. Return ROK.
747 * Invoked by: scheduler
749 * @param[in] RgSchRaCb *raCb
750 * @param[in] CmLteTimingInfo timingInfo
751 * @param[out] RgDlHqProc **hqP
753 * -#ROK if successful
754 * -#RFAILED otherwise
758 PUBLIC S16 rgSCHDhmGetMsg4HqProc
761 CmLteTimingInfo timingInfo
764 PUBLIC S16 rgSCHDhmGetMsg4HqProc (raCb, timingInfo)
766 CmLteTimingInfo timingInfo;
769 RgSchDlHqProcCb *tmpHqProc;
773 TRC2(rgSCHDhmGetMsg4HqProc)
776 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
779 /* No Harq Process available in the free queue. */
783 /* Remove the element from the free Queue and */
784 /* set the MSG 4 HARQ proc pointer */
785 //cmLListDelFrm(&hqE->free, tmp);
786 tmpHqProc = (RgSchDlHqProcCb *)(tmp->node);
787 rgSCHDhmHqPDelFrmFreeLst(tmpHqProc);
788 tmpHqProc->tbInfo[0].timingInfo = timingInfo;
789 hqE->msg4Proc = tmpHqProc;
792 } /* rgSCHDhmGetMsg4HqProc */
795 * @brief This function releases a HARQ process.
799 * Function: rgSCHDhmRlsHqpTb
800 * Purpose: This function resets the TB specific fields
801 * Based on the other TBs state, this HqProcess
802 * is returned to the HqEnt.
804 * 1. Add the HARQ process to the free queue.
805 * Invoked by: scheduler and HARQ processing
807 * @param[in] RgDlHqProc *hqP
808 * @param[in] U8 tbIdx
809 * @param[in] Bool togNdi
814 PUBLIC Void rgSCHDhmRlsHqpTb
816 RgSchDlHqProcCb *hqP,
821 PUBLIC Void rgSCHDhmRlsHqpTb(hqP, tbIdx, togNdi)
822 RgSchDlHqProcCb *hqP;
828 U8 othrTbIdx = tbIdx ^ 1;
830 RgSchCmnDlHqProc *cmnHqDl;
834 RgSchDlLcCb* lcCb = NULLP;
838 TRC2(rgSCHDhmRlsHqpTb)
840 /* Reset all tbInfo values */
845 if (hqP->hqE->ue != NULLP)
847 RgSchUeCb *ueCb = hqP->hqE->ue;
848 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
849 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
850 U8 cqi = dlUe->mimoInfo.cwInfo[0].cqi;
851 /* to get retransmission, decreasing transmission counter */
852 U16 numDlRetx = hqP->tbInfo[0].txCntr-1;
853 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
854 static U32 retxCnt1 = 0;
856 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, \
857 hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
862 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
865 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
868 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
871 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
874 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
875 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
876 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
877 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
878 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
880 retxCnt1 += numDlRetx;
882 #endif /* MAC_SCH_STATS */
883 RGSCH_ARRAY_BOUND_CHECK(0, hqP->tbInfo, tbIdx);
887 hqP->tbInfo[tbIdx].ndi ^= 1;
892 for (numLch =0; numLch < hqP->tbInfo[tbIdx].numLch; numLch++)
894 if (NULLP != (lcCb = rgSCHDbmGetDlDedLcCb( hqP->hqE->ue,
895 hqP->tbInfo[tbIdx].lchSchdDataArr[numLch].lcId)))
897 if (lcCb->lcType == CM_LTE_LCH_DTCH)
899 if (hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci])
901 hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]--;
904 if (!(hqP->hqE->ue->qciActiveLCs[lcCb->qciCb->qci]))
906 lcCb->qciCb->dlUeCount--;
914 hqP->tbInfo[tbIdx].tbSz = 0;
915 hqP->tbInfo[tbIdx].numLch = 0;
916 hqP->tbInfo[tbIdx].txCntr = 0;
917 /* FOR ACK NACK REP */
918 hqP->tbInfo[tbIdx].fbkRepCntr = 0;
919 hqP->tbInfo[tbIdx].fbkRecpRepCntr = 0;
920 hqP->tbInfo[tbIdx].ackCount = 0;
921 /* pdcch is moved from TbCb to HqCb.
922 This pdcch will be set to NULL when
923 HqCb will be pushed to free list*/
924 hqP->tbInfo[tbIdx].state = HQ_TB_ACKED;
925 hqP->tbInfo[tbIdx].isAckNackDtx = 0;
926 hqP->tbInfo[tbIdx].nackCount = 0;
927 hqP->tbInfo[tbIdx].dtxCount = 0;
928 hqP->tbInfo[tbIdx].schdTa.pres = NOTPRSNT;
929 hqP->tbInfo[tbIdx].contResCe = NOTPRSNT;
931 hqP->tbInfo[tbIdx].schdSCellActCe.pres = NOTPRSNT;
933 hqP->tbInfo[tbIdx].minRlcReordrTmr = 0;
934 /* Handling msg4 hqProc */
935 if (hqE->msg4Proc == hqP)
937 hqE->msg4Proc = NULLP;
940 /* Add the proc to the free list */
941 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
942 rgSCHDhmHqPAdd2FreeLst(hqP);
946 /* MS_WORKAROUND : syed The check (hqE->ccchSduProc != NULLP)
947 * is dangerous and it expects ccchSduProc is the first
948 * DL allocation for a UE, and considering a scenario
949 * of multiple UEs contending and 1 UE per TTI, this
950 * assumption can be wronged, leading to inUse list
951 * corruption. Hence altering this check.
952 * A better approach would be do avoid having this
953 * special handling for ccchSduProc, streamline
954 * it with the usual approach. */
955 if (hqE->ccchSduProc == hqP)
957 hqE->ccchSduProc = NULLP;
958 /* ccpu00137582- If hqP is in reTxLst then it will be no more available
959 * in inUse list, Hence need not to delete from inUse list*/
960 if(NULLP == hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node)
962 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
963 rgSCHDhmHqPDelFrmInUseLst(hqP);
967 hqP->tbInfo[tbIdx].ccchSchdInfo.retxLnk.node = NULLP;
971 /* Add the proc to the free list */
972 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
973 rgSCHDhmHqPAdd2FreeLst(hqP);
978 /* extra:check if other TB is also free for allocation then
979 * add it to FREE List */
980 switch(hqP->tbInfo[othrTbIdx].state)
983 /* Remove the element from the inUse Queue */
984 /* Freeing up the HARQ proc blocked for
985 * indefinite time in case of Retx */
986 if (hqP->tbInfo[tbIdx].cntrRetxAllocFail != RG_SCH_MAX_RETX_ALLOC_FAIL)
988 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
989 rgSCHDhmHqPDelFrmInUseLst(hqP);
994 rgEmtcsetNullSubFrm(hqP);
996 /* Add the proc to the free list */
997 //cmLListAdd2Tail(&hqE->free, &hqP->lnk);
998 rgSCHDhmHqPAdd2FreeLst(hqP);
1000 if (hqE->free.count > 8)
1003 printf("Crashing invalid hq count after free \n");
1004 printf("Crashing %d \n", *p);
1009 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
1012 cmnHqDl->spsAction = 0;
1013 cmnHqDl->isSpsActv = FALSE;
1014 cmnHqDl->isSpsSvcSchd = FALSE;
1019 /* Remove the element from the inUse Queue */
1020 /* Freeing up the HARQ proc blocked for
1021 * indefinite time in case of Retx */
1022 if (hqP->tbInfo[othrTbIdx].cntrRetxAllocFail == 0)
1024 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1025 rgSCHDhmHqPDelFrmInUseLst(hqP);
1033 hqP->tbInfo[tbIdx].cntrRetxAllocFail = 0;
1036 } /* rgSCHDhmRlsHqpTb */
1039 * @brief This function releases a HARQ process.
1043 * Function: rgSCHDhmRlsHqProc
1044 * Purpose: This function returns a HARQ process to HARQ Entity
1045 * in the DL direction.
1047 * 1. Add the HARQ process to the free queue.
1048 * Invoked by: scheduler and HARQ processing
1050 * @param[in] RgDlHqProc *hqP
1055 PUBLIC Void rgSCHDhmRlsHqProc
1057 RgSchDlHqProcCb *hqP
1060 PUBLIC Void rgSCHDhmRlsHqProc(hqP)
1061 RgSchDlHqProcCb *hqP;
1065 TRC2(rgSCHDhmRlsHqProc)
1068 #ifdef MAC_SCH_STATS
1069 /* THIS FUNCTION IS NOT CALLED */
1070 if (hqP->hqE->ue != NULLP)
1072 RgSchUeCb *ueCb = hqP->hqE->ue;
1073 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1074 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1075 U8 cqi = dlUe->mimoInfo.cwInfo[0].cqi;
1076 /* to get retransmission, decreasing transmission counter */
1077 U16 numDlRetx = hqP->tbInfo[0].txCntr-1;
1078 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1080 RG_SCH_CMN_DL_TBS_TO_MCS(tbs, hqRetxStats.dlCqiStat[(cqi - 1)].mcs);
1085 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1++;
1088 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2++;
1091 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3++;
1094 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4++;
1097 hqRetxStats.dlCqiStat[(cqi - 1)].totalTx = \
1098 hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_1 + \
1099 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_2 * 2) + \
1100 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_3 * 3) + \
1101 (hqRetxStats.dlCqiStat[(cqi - 1)].numOfHQ_4 * 4);
1103 #endif /* MAC_SCH_STATS */
1105 hqP->subFrm = NULLP;
1107 rgEmtcsetNullSubFrm(hqP);
1109 rgSCHDhmHqPDelFrmInUseLst(hqP);
1110 rgSCHDhmHqPAdd2FreeLst(hqP);
1116 } /* rgSCHDhmRlsHqProc */
1120 * @brief This function gets HARQ process with the given ID.
1124 * Function: rgSCHDhmGetHqProcFrmId
1125 * Purpose: This function returns the HARQ process with the given ID.
1128 * @param[in] RgSchUeCb *ue
1130 * @param[in] RgDlHqProc **hqP
1132 * -# ROK if successful
1133 * -# RFAILED otherwise
1137 PUBLIC S16 rgSCHDhmGetHqProcFrmId
1142 RgSchDlHqProcCb **hqP
1145 PUBLIC S16 rgSCHDhmGetHqProcFrmId(cell, ue, idx, hqP)
1149 RgSchDlHqProcCb **hqP;
1153 TRC2(rgSCHDhmGetHqProcFrmId)
1155 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1156 /* Pick the proc based on the index provided */
1157 *hqP = &(hqE->procs[idx]);
1160 } /* rgSCHDhmGetHqProcFrmId */
1163 * @brief This function gets SPS HARQ process from the given time
1167 * Function: rgSCHDhmSpsDlGetHqProc
1168 * Purpose: This function returns the SPS HARQ process for the given time
1170 * @param[in] RgSchUeCb *ue
1171 * @param[in] CmLteTimingInfo timingInfo
1172 * @return RgSchDlHqProcCb control block
1176 PUBLIC RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc
1180 CmLteTimingInfo timingInfo
1183 PUBLIC RgSchDlHqProcCb* rgSCHDhmSpsDlGetHqProc(cell, ue, timingInfo)
1186 CmLteTimingInfo timingInfo;
1191 RgSchDlHqProcCb *hqProc = NULLP;
1192 CmLList *tmp = NULLP;
1194 TRC2(rgSCHDhmSpsDlGetHqProc);
1196 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1198 CM_LLIST_FIRST_NODE(&(hqE->free), tmp);
1202 /* No Harq Process available in the free queue. */
1206 idx = ((timingInfo.sfn * RGSCH_NUM_SUB_FRAMES_5G + timingInfo.subframe)/
1207 ue->dl.dlSpsCfg.dlSpsPrdctyEnum) % ue->dl.dlSpsCfg.numSpsHqProc;
1210 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1212 /* If the HARQ process is in the free list, retrieve the process */
1213 while (hqProc->procId != idx)
1215 CM_LLIST_NEXT_NODE(&(hqE->free), tmp);
1220 hqProc = (RgSchDlHqProcCb *)(tmp->node);
1225 /* No Harq Process available in the free queue. */
1229 hqProc->tbInfo[0].timingInfo = timingInfo;
1230 hqProc->tbInfo[1].timingInfo = timingInfo;
1232 /* Remove the element from the free Queue */
1233 //cmLListDelFrm(&hqE->free, tmp);
1234 rgSCHDhmHqPDelFrmFreeLst(hqProc);
1236 /* Add the element into the inUse Queue as well */
1237 //cmLListAdd2Tail(&hqE->inUse, &hqProc->lnk);
1238 rgSCHDhmHqPAdd2InUseLst(hqProc);
1241 rgSCHLaaResetDlHqProcCb(hqProc);
1245 } /* rgSCHDhmSpsDlGetHqProc */
1246 #endif /* LTEMAC_SPS */
1249 /** * @brief Handler for handling TA.
1253 * Function : rgSCHDhmFdbkIndHndlTa
1255 * This function handles the TA state and values based on the
1256 * feedback indication received.
1258 * @param[in] RgSchDlHqProcCb *hqP
1259 * @param[in] U8 tbIdx
1260 * @param[in] U8 fdbk
1265 PRIVATE Void rgSCHDhmFdbkIndHndlTa
1267 RgSchDlHqProcCb *hqP,
1270 Bool maxHqRetxReached
1273 PRIVATE Void rgSCHDhmFdbkIndHndlTa(hqP, tbIdx, fdbk,maxHqRetxReached)
1274 RgSchDlHqProcCb *hqP;
1277 Bool maxHqRetxReached;
1283 TRC2(rgSCHDhmFdbkIndHndlTa)
1285 ueCb = hqP->hqE->ue;
1290 /*ccpu00130018 -ADD - To prevent duplicate insert into the TA list*/
1291 hqP->tbInfo[tbIdx].taSnt = FALSE;
1292 /* To prevent duplicate inserts of ueCb into TA list */
1293 if (ueCb->taLnk.node == NULLP)
1295 ueCb->taLnk.node = (PTR)ueCb;
1296 cmLListAdd2Tail(&cell->taUeLst, &ueCb->taLnk);
1301 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Trying to add CRNTI:%d into TA"
1302 "ACK List twice", ueCb->ueId);
1308 /* If Ta was sent and its the final NACK, then reset only the
1309 * taState to IDLE and not the value */
1310 /* Changed handling in case maxhqretx is reached for TA */
1311 if(TRUE == maxHqRetxReached)
1313 hqP->tbInfo[tbIdx].taSnt = FALSE;
1314 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1316 rgSCHUtlReTxTa(cell, ueCb);
1317 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
1318 "Nack Rcvd for TA. Max Tries Attempted");
1322 /* If Ta was sent and its the final NACK, then reset only the
1323 * taState to IDLE and not the value */
1324 if(TRUE == maxHqRetxReached)
1326 hqP->tbInfo[tbIdx].taSnt = FALSE;
1327 hqP->hqE->ue->dl.taCb.state = RGSCH_TA_IDLE;
1329 /*ccpu00131191 and ccpu00131317 - Fix for RRC Reconfig failure
1330 * issue for VoLTE call */
1331 rgSCHUtlDlTARpt(cell, ueCb);
1340 } /* rgSCHDhmFdbkIndHndlTa */
1342 /* 3.1 MIMO: TA cmd details at TB level rather than Hq Level */
1343 /** * @brief Handler for scheduling TA.
1347 * Function : rgSCHDhmShcdTa
1349 * This function is called by scheduler when resource allocation
1350 * for TA transmission is done.
1352 * @param[in] RgSchUeCb *ue
1353 * @param[out] RgSchDlHqTbCb *tbInfo
1358 PUBLIC Void rgSCHDhmSchdTa
1361 RgSchDlHqTbCb *tbInfo
1364 PUBLIC Void rgSCHDhmSchdTa(ueCb, tbInfo)
1366 RgSchDlHqTbCb *tbInfo;
1370 TRC2(rgSCHDhmSchdTa)
1372 ueCb->dl.taCb.state = RGSCH_TA_SCHEDULED;
1373 ueCb->dl.taCb.numRemSf = 2;
1374 tbInfo->schdTa.pres = PRSNT_NODEF;
1375 tbInfo->schdTa.val = ueCb->dl.taCb.ta;
1378 } /* rgSCHDhmSchdTa */
1381 /** * @brief Handler for fetching Harq Proc given the feeback information.
1385 * Function : rgSCHDhmHqProcByFdbkTime
1387 * This function shall fetch all the harq proc having the feedback
1388 * timing information.
1390 * @param[in] RgSchDlHqEnt *hqE
1391 * @param[in] CmLteTimingInfo timeInfo
1392 * @param[in] Bool *isMsg4
1393 * @param[out] RgSchDlHqProcCb **hqPrcs
1394 * @param[out] U8 *numTbs
1395 * @param[out] S8 *tbStrtIdx
1396 * @param[out] U8 *cntHqPrcs
1400 PRIVATE S16 rgSCHDhmHqProcByFdbkTime
1403 CmLteTimingInfo timeInfo,
1405 RgSchDlHqProcCb **hqPrcs,
1412 PRIVATE S16 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, isMsg4, hqPrcs,
1413 numTbs, tbStrtIdx, cntHqPrcs)
1415 CmLteTimingInfo timeInfo;
1417 RgSchDlHqProcCb **hqPrcs;
1424 RgSchDlHqTbCb *tbCb;
1425 RgSchDlHqProcCb *hqP;
1426 CmLteTimingInfo schdSfTime;
1427 RgSchTddDlAscSetIdxK ascIdx;
1438 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].fdbkTime, timeInfo))
1441 hqPrcs[*cntHqPrcs] = hqE->msg4Proc;
1442 tbStrtIdx[*cntHqPrcs] = 0;
1443 numTbs[*cntHqPrcs] = 1;
1448 ascIdx = rgSchTddDlAscSetIdxKTbl[cell->ulDlCfgIdx][timeInfo.subframe];
1449 noFdbks = ascIdx.numFdbkSubfrms;
1451 for(idx=0; idx<noFdbks; idx++)
1453 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
1454 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
1455 * serving the purpose */
1456 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime,ascIdx.subfrmNum[idx]);
1457 dlIdx = rgSCHUtlGetDlSfIdx(cell, &schdSfTime);
1458 lnk = &hqE->ue->dl.dlSfHqInfo[dlIdx].hqPLst;
1462 hqP = (RgSchDlHqProcCb*)node->node;
1465 numTbs[*cntHqPrcs] = 0;
1466 tbStrtIdx[*cntHqPrcs] = -1;
1467 for (i = 0; i < 2; i++)
1469 /* Extra:check which TB is waiting for feedback */
1470 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1472 if (tbStrtIdx[*cntHqPrcs] == -1)
1474 tbStrtIdx[*cntHqPrcs] = i;
1476 numTbs[*cntHqPrcs]++;
1479 if (numTbs[*cntHqPrcs] > 0)
1481 hqPrcs[*cntHqPrcs] = hqP;
1486 /* AN REP Hq Procs */
1487 node = cell->subFrms[dlIdx]->ackNakRepQ.first;
1490 tbCb = (RgSchDlHqTbCb *)(node->node);
1493 numTbs[*cntHqPrcs] = 0;
1494 tbStrtIdx[*cntHqPrcs] = -1;
1495 for (i = 0; i < 2; i++)
1497 /* Extra:check which TB is waiting for feedback */
1498 if (hqP->tbInfo[i].state == HQ_TB_WAITING)
1500 if (tbStrtIdx[*cntHqPrcs] == -1)
1502 tbStrtIdx[*cntHqPrcs] = i;
1504 numTbs[*cntHqPrcs]++;
1507 if (numTbs[*cntHqPrcs] == 2)
1511 if (numTbs[*cntHqPrcs] > 0)
1513 hqPrcs[*cntHqPrcs] = hqP;
1525 /** * @brief Handler for fetching Harq Proc given the timming information.
1529 * Function : rgSCHDhmHqProcByTime
1531 * This function shall fetch the harq proc using the timing information.
1533 * @param[in] RgSchDlHqEnt *hqE
1534 * @param[in] CmLteTimingInfo timeInfo
1535 * @param[in] Bool *isMsg4
1536 * @param[out] U8 *numTbs
1537 * @param[out] S8 *tbStrtIdx
1538 * @return RgSchDlHqProcCb*
1539 * -# RgSchDlHqProcCb*
1543 PUBLIC RgSchDlHqProcCb *rgSCHDhmHqProcByTime
1546 CmLteTimingInfo timeInfo,
1551 PUBLIC RgSchDlHqProcCb *rgSCHDhmHqProcByTime(hqE, timeInfo,
1554 CmLteTimingInfo timeInfo;
1561 if (RGSCH_TIMEINFO_SAME(hqE->msg4Proc->tbInfo[0].timingInfo, timeInfo))
1564 RETVALUE(hqE->msg4Proc);
1572 /** * @brief Handler for handling the harq transaction failure.
1576 * Function : rgSCHDhmHqTbTrnsFail
1578 * This function handled the harq TB transaction failure :
1579 * - If retries have not reached maximum, add to the reTx Q.
1580 * - else do error recovery.
1582 * @param[in] RgSchCellCb *cell
1583 * @param[in] RgSchDlHqProcCb *hqP
1584 * @param[in] U8 tbCnt
1585 * @param[out] Bool *isMaxRetx
1591 PUBLIC Void rgSCHDhmHqTbTrnsFail
1594 RgSchDlHqProcCb *hqP,
1599 PUBLIC Void rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, isMaxRetx)
1601 RgSchDlHqProcCb *hqP;
1609 TRC2(rgSCHDhmHqTbTrnsFail)
1613 /* Fetch the maximum number of harq transmissions */
1614 if (hqE->msg4Proc == hqP)
1617 if(hqP->hqE->raCb->expiryTime.sfn == RGSCH_CONTRES_EXP)
1619 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1620 "rgSCHDhmHqTbTrnsFail contRes exp(): tmpCRNTI = %u",
1621 hqP->hqE->raCb->tmpCrnti);
1622 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1626 maxHqTx = cell->dlHqCfg.maxMsg4HqTx;
1630 maxHqTx = hqE->maxHqTx;
1633 #ifdef MAC_SCH_STATS
1634 if (hqE->ue != NULLP)
1636 RgSchUeCb *ueCb = hqE->ue;
1637 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
1638 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
1639 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
1640 static U32 retxCnt = 0;
1644 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
1646 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
1647 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
1649 #endif /* MAC_SCH_STATS */
1651 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, hqP->tbInfo, tbCnt);
1652 /* Reset the PDCCH reference */
1654 if (hqP->tbInfo[tbCnt].txCntr < maxHqTx)
1656 hqP->tbInfo[tbCnt].state = HQ_TB_NACKED;
1658 if((hqE->ue != NULLP) && (hqE->ue->isDrxEnabled == TRUE))
1661 /*If DRX is enabled for the UE, we need to start the HARQ RTT timer
1662 * for the UE. Addtion to the retransmission queue will be done on
1663 * HARQ RTT timer expiry.--*/
1664 switch(hqP->tbInfo[tbCnt ^ 1].state)
1667 /*As the first TB is ACKED we have not started HARQ RTT for the
1668 * HqP, so start it here.*/
1669 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1670 rgSCHDhmHqPDelFrmInUseLst(hqP);
1672 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP, tbCnt);
1675 /* Integration fix */
1676 /* Setting cntrRetxAllocFail to MAX value here */
1677 /* Since the hqP entry is already deleted from inUse list of HqEntity
1678 setting the value here will ensure the entry is not deleted
1679 again during release harq proc */
1680 if ( (hqP->sch != (RgSchCmnDlHqProc *)NULLP) &&
1681 (RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)))
1683 hqP->tbInfo[0].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1684 if (hqP->tbInfo[1].txCntr)
1686 hqP->tbInfo[1].cntrRetxAllocFail = RG_SCH_MAX_RETX_ALLOC_FAIL;
1692 /*As the first TB is NACKED we have already started HARQ RTT for the
1693 * HqP, so dont start it here, just delete from in use queue.*/
1694 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1695 rgSCHDhmHqPDelFrmInUseLst(hqP);
1698 /*As this is the first TB to be fed back and is NACKED start
1699 * the HARQ RTT here.*/
1701 rgSCHDrxStartHarqRTTTmr(hqP->hqE->ue->cell, hqP,tbCnt);
1707 /* extra:check if already removed as part of other TB processing
1708 * then donot remove from InUse Q */
1709 /* Check if other TB is not waiting for feedback.
1710 * Makinf sure hqP is present in inUse Queue until
1711 * it is fedback for all its TBs */
1712 switch(hqP->tbInfo[tbCnt ^ 1].state)
1715 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1716 if(hqE->msg4Proc != hqP)
1718 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1719 rgSCHDhmHqPDelFrmInUseLst(hqP);
1721 /* Retransmission needs to be done. Add to the scheduler Q */
1722 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1725 /*Fix for ccpu00113296 - Do not delete for Msg4 Harq Entities*/
1726 if(hqE->msg4Proc != hqP)
1728 //cmLListDelFrm(&hqE->inUse, &hqP->lnk);
1729 rgSCHDhmHqPDelFrmInUseLst(hqP);
1733 /* Retransmission needs to be done. Add to the scheduler Q */
1735 rgSCHUtlDlProcAddToRetx(hqP->hqE->cell, hqP);
1743 /* Failure Notification */
1744 if (hqE->msg4Proc == hqP)
1746 /* SR_RACH_STATS : MSG4 Max Retx Fail*/
1747 rgNumMsg4FailMaxRetx++;
1749 hqE->cell->tenbStats->sch.msg4Fail ++;
1752 /* Perform RAM MSG4 done processing */
1753 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1754 "rgSCHDhmHqTbTrnsFail(): hq max retx fail: tmpCRNTI = %u",
1755 hqP->hqE->raCb->tmpCrnti);
1756 rgSCHRamMsg4Done(cell, (RgSchRaCb *)hqP->hqE->raCb);
1760 /* Release the Harq Proc */
1761 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
1767 } /* rgSCHDhmHqTbTrnsFail */
1769 PUBLIC U32 rgHqRvStats[2][4][2] = {{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
1770 {{0, 0}, {0, 0}, {0, 0}, {0, 0}}};
1773 /** * @brief Function to decode the position of HarqFb for M=1.
1777 * Function : rgSchGetHqFdbkPosForM1
1779 * @param[in] RgSchUeCb *ue,
1780 * @param[in] RgSchDlHqProcCb *hqP,
1781 * @param[in] U8 *isAck,
1782 * @param[in] RgTfuHqInfo *fdbk,
1783 * @param[in] U8 tbIdx,
1784 * @param[in] RgSchTddANInfo *anInfo;
1788 PRIVATE Void rgSchGetHqFdbkPosForM1
1791 RgSchDlHqProcCb *hqP,
1795 RgSchTddANInfo *anInfo
1798 PRIVATE Void rgSchGetHqFdbkPosForM1(ue,hqP,isAck,fdbk,tbIdx,anInfo)
1800 RgSchDlHqProcCb *hqP;
1804 RgSchTddANInfo *anInfo;
1809 /* handle pusch and pucch cases */
1810 /* PUSCH:: Fdbks are in the increasing order
1811 * of servCellIdx as per 36.212 section 5.2.26*/
1812 switch(ue->f1bCsAVal)
1814 case RG_SCH_A_VAL_2:
1816 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1818 *isAck = fdbk->isAck[1];/*SCell*/
1822 *isAck = fdbk->isAck[0];/*PCell*/
1826 case RG_SCH_A_VAL_3:
1828 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1830 U8 cellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
1831 hqP->hqE->cell->cellId,
1834 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[cellIdx]->txMode.txModeEnum) > 1)
1835 {/*SCell - mimo mode*/
1836 if(TRUE == fdbk->isPusch)
1838 *isAck = fdbk->isAck[tbIdx + 1];
1842 *isAck = fdbk->isAck[tbIdx];
1846 {/*SCell - siso mode*/
1847 *isAck = fdbk->isAck[2];
1851 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1852 {/*Primary Cell - mimo mode*/
1853 *isAck = fdbk->isAck[tbIdx];
1856 {/*Primary Cell - siso mode*/
1857 if((TRUE == fdbk->isPusch) && (FALSE == anInfo->isSpsOccasion))
1859 /* If fdbk is on PUSCH but its not an SPS occasion*/
1860 *isAck = fdbk->isAck[0];
1864 /* If fdbk is on PUCCH or its an SPS occasion*/
1865 *isAck = fdbk->isAck[2];
1871 case RG_SCH_A_VAL_4:
1873 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
1875 *isAck = fdbk->isAck[tbIdx + 2];
1879 *isAck = fdbk->isAck[tbIdx];
1888 }/* End of rgSchGetHqFdbkPosForM1 */
1890 /** * @brief Function to decode the position of HarqFb for M>=2 cases.
1894 * Function : rgSchGetHqFdbkPosForM234
1896 * @param[in] RgSchUeCb *ue,
1897 * @param[in] RgSchDlHqProcCb *hqP,
1898 * @param[in] U8 *isAck,
1899 * @param[in] RgTfuHqInfo *fdbk,
1900 * @param[in] U8 tbIdx,
1901 * @param[in] RgSchTddANInfo *anInfo;
1902 * @param[in] CmLteTimingInfo timeInfo;
1906 PRIVATE Void rgSchGetHqFdbkPosForM234
1909 RgSchDlHqProcCb *hqP,
1913 RgSchTddANInfo *anInfo,
1915 CmLteTimingInfo timeInfo
1918 PRIVATE Void rgSchGetHqFdbkPosForM234(ue,hqP,isAck,fdbk,tbIdx,anInfo,M,timeInfo)
1920 RgSchDlHqProcCb *hqP;
1924 RgSchTddANInfo *anInfo;
1926 CmLteTimingInfo timeInfo;
1931 RgSchTddANInfo *pCellAnInfo;
1936 isSCell = RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell);
1937 pCellAnInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo, RGSCH_PCELL_INDEX);
1939 if(TRUE == fdbk->isPusch)
1943 if (anInfo->wUlDai == 3)
1945 incr = anInfo->wUlDai;
1951 if(1 == anInfo->ulDai)
1953 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) +
1954 hqP->tbInfo[tbIdx].tbIdx + incr;
1958 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + incr;
1963 if(1 == anInfo->ulDai)
1965 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
1967 fdbkIdx = (hqP->tbInfo[tbIdx].dai - 1) + (hqP->tbInfo[tbIdx].tbIdx);
1971 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1976 fdbkIdx = (hqP->tbInfo[tbIdx].dai) - 1;
1984 /* pucchFdbkIdx is set to DAI hence -1 to get index */
1985 fdbkIdx = ((hqP->tbInfo[tbIdx].pucchFdbkIdx) + M -1);
1991 /* SPS occasion feedback in case of M > 2 will
1992 * be always present in the index 0*/
1994 if(hqP->spsN1PucchRes.pres == TRUE)
1995 {/* SPS occasion hq proc */
1999 if((NULLP != pCellAnInfo) &&
2000 (pCellAnInfo->dlDai != pCellAnInfo->ulDai))
2002 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx;
2004 {/* NO SPS occasion was present in the bundle*/
2005 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
2010 fdbkIdx = hqP->tbInfo[tbIdx].pucchFdbkIdx - 1;
2014 *isAck = fdbk->isAck[fdbkIdx];
2016 static RgSchDlHqProcCb *temp = NULLP;
2017 if (temp != hqP->tbInfo[tbIdx].hqP)
2019 statsCnt = statsCnt % 10000;
2020 dlHqStats[statsCnt].cellId = hqP->hqE->cell->cellId;
2021 dlHqStats[statsCnt].sfn = hqP->tbInfo[tbIdx].timingInfo.sfn;
2022 dlHqStats[statsCnt].sf = hqP->tbInfo[tbIdx].timingInfo.subframe;
2023 dlHqStats[statsCnt].ack = *isAck;
2024 dlHqStats[statsCnt].fdbkIdx = fdbkIdx;
2025 dlHqStats[statsCnt].ue = hqP->hqE->ue->ueId;;
2027 dlHqStats[statsCnt].ulDai = incr;
2028 if(TRUE == fdbk->isPusch)
2030 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].dai;
2034 dlHqStats[statsCnt].dlDai = hqP->tbInfo[tbIdx].pucchFdbkIdx;
2038 dlHqStats[statsCnt].ack0 = fdbk->isAck[0];
2039 dlHqStats[statsCnt].ack1 = fdbk->isAck[1];
2040 dlHqStats[statsCnt].ack2 = fdbk->isAck[2];
2041 dlHqStats[statsCnt].ack3 = fdbk->isAck[3];
2042 dlHqStats[statsCnt].ack4 = fdbk->isAck[4];
2043 dlHqStats[statsCnt].ack5 = fdbk->isAck[5];
2044 dlHqStats[statsCnt].ack6 = fdbk->isAck[6];
2045 dlHqStats[statsCnt].ack7 = fdbk->isAck[7];
2048 temp = hqP->tbInfo[tbIdx].hqP;
2053 }/*rgSchGetHqFdbkPosForM234*/
2057 * @brief Handler for HARQ feedback received for DL transmission.
2061 * Function : rgSCHDhmHqFdbkInd
2063 * This function shall act on the feedback received from TOM for DL
2064 * transmission. If the feedback for msg4 is final (after max transmissions
2065 * or ACK) inform RAM that Msg4 transmission is done.
2068 * @param[in] Void *cb
2069 * @param[in] U8 cbType
2070 * @param[in] RgSchCellCb cellCb
2071 * @param[in] CmLteTimingInfo timeInfo
2072 * @param[in] TfuHqInfo *fdbk
2073 * @param[in] RgInfRlsHqInfo *rlsHqBufs
2074 * @param[in] RgSchErrInfo *err
2080 PUBLIC S16 rgSCHDhmHqFdbkInd
2084 RgSchCellCb *cellCb,
2085 CmLteTimingInfo timeInfo,
2087 RgInfRlsHqInfo *rlsHqBufs,
2091 PUBLIC S16 rgSCHDhmHqFdbkInd(cb, cbType, cellCb, timeInfo, fdbk, rlsHqBufs, err)
2094 RgSchCellCb *cellCb;
2095 CmLteTimingInfo timeInfo;
2097 RgInfRlsHqInfo *rlsHqBufs;
2101 RgSchCellCb *sCell = NULLP;
2103 /*ccpu00127339 - MOD - change to avoid the crash*/
2104 RgSchUeCb *ue = NULLP;
2106 Bool isMsg4 = FALSE;
2107 RgSchRaCb *raCb = NULLP;
2109 /* Maximum possible HARQ processes in UL-DL configuration 5 that is
2110 * given feedback at a time */
2111 RgSchDlHqProcCb *hqPrcs[(RGSCH_NUM_SUB_FRAMES-1)*5]; /*MAX 5 Cells*/
2112 U8 numTb[(RGSCH_NUM_SUB_FRAMES-1)*5];
2113 S8 tbStrtIdx[(RGSCH_NUM_SUB_FRAMES-1)*5];
2116 RgSchTddANInfo *anInfo = NULLP;
2119 RgrTddAckNackMode ackNackMode;
2121 RgSchDlSf *nxtDlsf = NULLP;
2122 /* U8 rcvCnt = 0; */
2123 CmLteTimingInfo nxtfrm = {0,0};
2125 Bool maxHqRetxReached;
2127 Bool hasRelPdcch = FALSE;
2130 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2131 RgSchTddDlAscSetIdxK ascIdx;
2135 #ifdef LTEMAC_SPS_AN_MUX
2136 Bool isPusch = FALSE;
2139 /* Subframes in which transmissions are scheduled and whose feedback can come
2140 * in this subframe. Used only for Multiplexing mode */
2141 CmLteTimingInfo schdSfTime[RGSCH_TDD_MAX_FDBK];
2142 #ifdef RGSCH_SPS_STATS
2143 RgSchCmnDlHqProc *cmnHqDl;
2147 U8 sCellActCePres = 0;
2149 /* LTEMAC_SPS_AN_MUX*/
2150 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
2151 TRC2(rgSCHDhmHqFdbkInd)
2153 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
2155 raCb = (RgSchRaCb *)(cb);
2156 ackNackMode = RGR_TDD_ACKNACK_MODE_BUNDL;
2158 /* ccpu00139061 Fix */
2159 rnti = raCb->tmpCrnti;
2163 ue = (RgSchUeCb *)(cb);
2164 ackNackMode = ue->dl.ackNackMode;
2165 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cellCb);
2167 #ifdef LTEMAC_SPS_AN_MUX
2168 isPusch = fdbk->isPusch;
2172 if (RGSCH_TIMEINFO_SAME(timeInfo, ue->relPdcchFbkTiming))
2179 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2180 ascIdx = rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][timeInfo.subframe];
2181 noFdbks = ascIdx.numFdbkSubfrms;
2183 #ifdef LTEMAC_SPS_AN_MUX
2184 /* Calculate the subframe time at which transmissions should have happened to
2185 * receive feedback in this subframe */
2186 if (ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2188 for(idx=0; idx<noFdbks; idx++)
2190 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
2191 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
2192 * serving the purpose */
2193 RGSCHDECRFRMCRNTTIME(timeInfo,schdSfTime[idx],ascIdx.subfrmNum[idx]);
2198 rgSCHDhmHqProcByFdbkTime(hqE, timeInfo, &isMsg4, hqPrcs, numTb, \
2199 tbStrtIdx, &hqCnt,hqE->cell);
2200 /* Fetch the harqProc from the inUse list */
2202 if ((FALSE == hasRelPdcch) && (hqCnt == 0))
2206 err->errType = RGSCHERR_DHM_FDBK_IND;
2207 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2211 /* ccpu00147469 : This code is moved below as here this code always try to
2212 * get the primary cell aninfo. it is due to hqE->cell->cellId as it is
2216 if(fdbk->hqFdbkMode == TFU_ACK_NACK_SPECIAL_BUNDLING)
2218 rgSCHDhmPrcSplBundlFdbk(cellCb, fdbk, hqCnt);
2224 #ifdef LTEMAC_SPS_AN_MUX
2225 /* Check if feedback came on configured UL SPS grant in Muxing mode */
2226 if((ackNackMode == RGR_TDD_ACKNACK_MODE_MULT) &&
2230 /* Pick the valid feedbacks out of M feedbacks */
2231 for(idx=0; idx<noFdbks; idx++)
2233 /* Skip the feedback if hqProc[idx] did not transmit in schdSf[idx]
2234 * and no release pdcch is sent in prevTime */
2235 /* TODO: SPS_TDD: Check this while testing */
2236 if ((hqPrcs[hIdx] && !RGSCH_TIMEINFO_SAME(hqPrcs[hIdx]->\
2237 tbInfo[(S16)(tbStrtIdx[hIdx])].timingInfo,\
2238 schdSfTime[idx])) &&
2239 !RGSCH_TIMEINFO_SAME(ue->relPdcchTxTime, schdSfTime[idx]))
2241 /* Discard the feedback which is corresponding to a subframe in
2242 * which no DL transmission took place */
2244 while(tmpIdx < noFdbks)
2246 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2247 fdbk->isAck[tmpIdx-1] = fdbk->isAck[tmpIdx];
2253 } /* end of for loop */
2254 } /* end of configured UL SPS grant check */
2266 for(idx=0;idx < hqCnt; idx++)
2268 /* Fix for CR ccpu00147469: Get the anInfo for each harq proc */
2272 U8 servCellIdx = rgSchUtlGetServCellIdx(hqPrcs[idx]->hqE->cell->instIdx,
2273 hqPrcs[idx]->hqE->cell->cellId,ue);
2275 if(ue->cellInfo[servCellIdx]->sCellState != RG_SCH_SCELL_ACTIVE)
2279 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,servCellIdx);
2281 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,RGSCH_PCELL_INDEX);
2285 RGSCHDBGINFO(cellCb->instIdx,(rgSchPBuf(cellCb->instIdx),
2286 "Ack Rcvd. No Ack/Nack feedback available \n"));
2291 sCell = hqPrcs[idx]->hqE->cell;
2292 rlsHqBufs = &(sCell->rlsHqArr[sCell->crntHqIdx]);
2293 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
2294 for (tbCnt = tbStrtIdx[idx]; (tbCnt-tbStrtIdx[idx]) < numTb[idx]; tbCnt++)
2296 /* Fix : syed MultiUe per TTI crash in TA List. */
2298 maxHqRetxReached = FALSE;
2299 /* Remove the harq process from the subframe */
2300 sf = rgSCHUtlSubFrmGet(cellCb, hqPrcs[idx]->tbInfo[tbCnt].timingInfo);
2304 uciFrmtTyp = ue->dl.dlSfHqInfo[cellCb->cellId][sf->dlIdx].uciFrmtTyp;
2307 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
2309 if((fdbk->hqFdbkMode != TFU_ACK_NACK_SPECIAL_BUNDLING)&&
2310 (RGR_TDD_ACKNACK_MODE_MULT == ackNackMode))
2312 isAck = fdbk->isAck[hqPrcs[idx]->tbInfo[tbCnt].m];
2316 /* TODO: review for TM4 and CA interaction */
2317 if((TRUE == hqPrcs[idx]->cwSwpEnabled) && (1 < numTb[idx]))
2319 isAck = fdbk->isAck[!tbCnt];
2323 isAck = fdbk->isAck[tbCnt];
2332 rgSchGetHqFdbkPosForM1(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo);
2336 rgSchGetHqFdbkPosForM234(ue, hqPrcs[idx], &isAck, fdbk, tbCnt, anInfo, noFdbks, timeInfo);
2342 /* revanth tweakin AN PUSCH to ACK always */
2343 if (hqPrcs[idx]->isPuschFdbk)
2349 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2350 if(cellCb->ulDlCfgIdx != 5)
2352 rgSCHUtlGetNxtDlSfInfo(hqPrcs[idx]->tbInfo[tbCnt].timingInfo,\
2353 cellCb, sf, &nxtDlsf, &nxtfrm);
2355 /* Keep a tab on how many ACKs or NACKs we have received */
2356 if (isAck == TFU_HQFDB_ACK)
2358 hqPrcs[idx]->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2359 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][0]++;
2361 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2362 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2364 /* Do not update the Ul Trans Time in case of raCb */
2367 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2369 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2373 else if (isAck == TFU_HQFDB_NACK)
2375 hqPrcs[idx]->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2376 rgHqRvStats[tbCnt][hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv][1]++;
2378 sCell->tenbStats->sch.dlNack[tbCnt]\
2379 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2380 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2381 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2383 /* Do not update the Ul Trans Time in case of raCb */
2386 rgSCHUtlHdlUlTransInd(cellCb, ue, timeInfo);
2388 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2389 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt] ++;
2393 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2395 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2401 hqPrcs[idx]->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2403 sCell->tenbStats->sch.dlDtx[tbCnt]\
2404 [hqPrcs[idx]->tbInfo[tbCnt].dlGrnt.rv]++;
2407 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt] ++;
2411 if(hqPrcs[idx]->tbInfo[tbCnt].txCntr == 1)
2413 cellCb->dlUlTbCnt.tbTransDlFaulty++;
2418 if(ue && RG_SCH_IS_CELL_SEC(ue,hqPrcs[idx]->hqE->cell))
2420 if(isAck == TFU_HQFDB_ACK)
2422 gSCellTb1AckCount++;
2423 gSCellTb2AckCount++;
2424 }else if(isAck == TFU_HQFDB_NACK)
2426 gSCellTb1NackCount++;
2427 gSCellTb2NackCount++;
2430 gSCellTb1DtxCount++;
2431 gSCellTb2DtxCount++;
2436 if(isAck == TFU_HQFDB_ACK)
2438 gPCellTb1AckCount++;
2439 gPCellTb2AckCount++;
2440 }else if(isAck == TFU_HQFDB_NACK)
2442 gPCellTb1NackCount++;
2443 gPCellTb2NackCount++;
2446 gPCellTb1DtxCount++;
2447 gPCellTb2DtxCount++;
2451 /* Check if this is repeating UE */
2452 if (hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr != 0)
2454 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, TRUE);
2455 /* Check if last repetition */
2456 if (--hqPrcs[idx]->tbInfo[tbCnt].fbkRepCntr)
2458 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
2459 /* Update feedback time for this hqP TB so that
2460 * next subframe its picked up */
2461 RGSCH_UPD_HQAN_FDBKTIME(&hqPrcs[idx]->tbInfo[tbCnt],\
2463 RGSCH_NULL_CHECK(cellCb->instIdx, anInfo);
2464 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, &hqPrcs[idx]->tbInfo[tbCnt]);
2468 /* For a repeating UE take the decision here */
2469 /* For a repeating UE take the decision here */
2470 if (((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2471 ((hqPrcs[idx]->tbInfo[tbCnt].ackCount) > (hqPrcs[idx]->tbInfo[tbCnt].dtxCount)))
2473 isAck = TFU_HQFDB_ACK;
2475 else if (((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].nackCount)) &&
2476 ((hqPrcs[idx]->tbInfo[tbCnt].dtxCount) > (hqPrcs[idx]->tbInfo[tbCnt].ackCount)))
2478 isAck = TFU_HQFDB_DTX;
2482 isAck = TFU_HQFDB_NACK;
2484 hqPrcs[idx]->tbInfo[tbCnt].isAckNackDtx = isAck;
2488 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqPrcs[idx], tbCnt, FALSE);
2491 if (((isAck == TFU_HQ_NACK) || (isAck == TFU_HQ_ACK)) &&
2492 ((hqPrcs[idx]->sch != (RgSchCmnDlHqProc *)NULLP) &&
2493 (RG_SCH_CMN_SPS_DL_IS_SPS_TX_HQP(hqPrcs[idx])))
2496 /* ACK or NACK received for SPS ACTV PDCCH
2497 * Hence consider SPS ACTVN PDCCH received successfully */
2498 rgSCHUtlDlProcAck(cellCb, hqPrcs[idx]);
2501 if(TFU_HQFDB_ACK == isAck)
2508 raCb = rgSCHDbmGetRaCb(cellCb, rnti);
2510 /* Inform Random Access Module regarding the ack received */
2513 /*RRC Connection Setup failure issue where RRC connection
2514 * setup was not reaching UE due to message 4 HARQ failure */
2515 #ifdef XEON_SPECIFIC_CHANGES
2516 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Msg4 Harq SUCCESS for UE(%d)\n", rnti);
2518 rgSCHRamMsg4Done(cellCb, raCb);
2521 else /*ccpu00114124- HARQ Release for Msg4 */
2524 /*Update feedback history for every Tx/Retx */
2525 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2527 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2528 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2530 /* Store activation CE presence as it is required later to start
2531 *activation delay timer */
2532 sCellActCePres = hqPrcs[idx]->tbInfo[tbCnt].schdSCellActCe.pres;
2534 rgSCHDhmRlsHqpTb(hqPrcs[idx], tbCnt, TRUE);
2540 /* If this Msg4 DTX, there will be
2541 * no DlHqProc as it has its own HarqProc */
2544 rgSCHDhmHqTbTrnsFail(cellCb, hqPrcs[idx], tbCnt, &hqRls);
2545 maxHqRetxReached = hqRls;
2547 if ((isMsg4 == FALSE))
2549 /*Update feedback history for every Tx/Retx */
2550 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2553 if (isMsg4 == FALSE)
2555 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2556 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
2563 /* MS_WORKAROUND: to increase Harq Fail Counter .
2564 The status field is required for tracking the number of harq faliures at MAC*/
2567 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2568 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
2572 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
2573 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
2575 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
2576 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
2577 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
2581 if (hqPrcs[idx]->tbInfo[tbCnt].taSnt == TRUE)
2583 rgSCHDhmFdbkIndHndlTa(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2586 /* Handle Scell activation */
2587 if (TRUE == sCellActCePres)
2589 /* Primary Cellcb needs to be retrived
2590 * if the feedback is coming on pusch of
2591 * sec cell. THis needs to be considered
2593 rgSCHSCellHndlFdbkInd(hqPrcs[idx], tbCnt, isAck, maxHqRetxReached);
2599 hqPrcs[idx]->cwSwpEnabled = FALSE;
2601 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
2603 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
2604 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
2605 hqPrcs[idx]->procId;
2606 rlsHqBufs->numUes++;
2609 hqPrcs[idx]->isPuschFdbk = 0;
2614 /*it is possible for some TDD configurations (like TDD cfg 5)
2615 * to have multiple feedback for 13 subframes before. It is
2616 * possible in such a case to have a release sent after data
2617 * thus running into a situation where we are receiving feedback
2618 * for both data and relese pdcch
2621 if ( (hqCnt == 0) ||
2622 (hasRelPdcch && rcvCnt > hqCnt)
2625 if (ue && hasRelPdcch)
2627 /* Bool found = FALSE; */
2629 sf = rgSCHUtlSubFrmGet(cellCb, ue->relPdcchTxTime);
2639 #if ((defined LTEMAC_SPS_AN_MUX) || (defined LTE_ADV))
2640 if(ackNackMode == RGR_TDD_ACKNACK_MODE_MULT)
2642 CmLteTimingInfo txTime;
2647 ulDlCfgIdx = cellCb->ulDlCfgIdx;
2649 maxFdbks = rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx]
2650 [timeInfo.subframe].
2653 for(itr=0; itr< maxFdbks; itr++)
2656 /* Handling the case of only SPS release pdcch
2657 * and no other scheduling in both the serving cells
2659 if(ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
2660 {/* Using the sorted K table */
2661 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2662 rgSchTddDlHqPucchResCalTbl[ulDlCfgIdx][timeInfo.subframe].subfrmNum[itr]);
2666 RGSCHDECRFRMCRNTTIME (timeInfo, txTime,
2667 rgSchTddDlAscSetIdxKTbl[ulDlCfgIdx][timeInfo.subframe].subfrmNum[itr]);
2670 if (RGSCH_TIMEINFO_SAME (txTime, ue->relPdcchTxTime))
2673 if((ue->uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)&&
2676 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
2678 isAck = fdbk->isAck[0];
2681 isAck = fdbk->isAck[2];
2685 /* M > 1 same below logic apply.
2686 If SPS occasion and rel pdcch is present
2687 SPS occasion after SPS release cannot
2692 isAck = fdbk->isAck[itr];
2695 rgSCHUtlDlRelPdcchFbk(cellCb, ue, isAck);
2697 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2698 /* Remove release PDCCH from the subframe */
2699 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2700 sf->relPdcch = NULLP;
2710 RGSCH_NULL_CHECK(cellCb->instIdx, sf->relPdcch);
2711 /* Remove release PDCCH from the subframe */
2712 rgSCHUtlPdcchPut(cellCb, &sf->pdcchInfo, sf->relPdcch);
2713 sf->relPdcch = NULLP;
2715 rgSCHUtlDlRelPdcchFbk(cellCb, ue, fdbk->isAck[0]);
2718 if ( found == FALSE )
2720 RGSCH_NULL_CHECK(cellCb->instIdx, ue);
2721 RLOG_ARG3(L_ERROR,DBG_CELLID,cellCb->cellId,"CRNTI:%d"
2722 " NO HARQ proc available for feedback:timeInfo:snf %d,subframe %d",
2723 ue->ueId,timeInfo.sfn, timeInfo.subframe);
2724 err->errType = RGSCHERR_DHM_FDBK_IND;
2725 err->errCause = RGSCHERR_DHM_FDBK_IND_INVALID_CB;
2730 #endif /* LTEMAC_SPS */
2731 /* Initialise the Ack/Nack feedback */
2732 /* [ccpu00127651] - MOD For Msg4 Harq Proc, anInfo will not be filled while
2733 scheduling. So added a condition !isMsg4 to avoid calling the function
2734 rgSCHUtlInitUeANFdbkInfo*/
2735 if((ue) && (!anUpd) && (!isMsg4))
2738 /* TODO:: Initi the anInfo all the serving cells */
2739 for(idx = 0; idx <= RG_SCH_MAX_SCELL; idx++)
2741 if(ue->cellInfo[idx])
2743 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &timeInfo,idx);
2744 /* Fix for CR ccpu00147693: If anInfo is there then initialize it
2745 * else don't do anything. basically continue for next serving
2749 rgSCHUtlInitUeANFdbkInfo(anInfo);
2754 rgSCHUtlInitUeANFdbkInfo(anInfo);
2760 //#endif /* LTEMAC_SPS */
2763 /** * @brief Handler for HARQ feedback received for DL transmission.
2767 * Function : rgSCHDhmPrcFdbkForTb
2769 * Process Hq Prc Fdbk for a TB
2771 * @param[in] RgSchCellCb *cell
2772 * @param[in] RgTfuHarqAckIndInfo *fdbk
2773 * @param[in] RgSchErrInfo *err
2779 PUBLIC S16 rgSCHDhmPrcFdbkForTb
2783 RgSchDlHqProcCb *hqP,
2788 CmLteTimingInfo timingInfo,
2790 RgInfRlsHqInfo *rlsHqBufs,
2794 PUBLIC S16 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt, timingInfo, isAck, rlsHqBufs, err)
2797 RgSchDlHqProcCb *hqP;
2802 CmLteTimingInfo timingInfo;
2804 RgInfRlsHqInfo *rlsHqBufs;
2809 Inst inst = cell->instIdx;
2811 #ifdef RGSCH_SPS_STATS
2812 RgSchCmnDlHqProc *cmnHqDl;
2815 RgSchRaCb *raCb = NULLP;
2817 Bool hqFreed =FALSE;
2818 Bool maxHqRetxReached = FALSE;
2819 RgSchCmnDlUe *ueDl = NULLP;
2820 RgSchCellCb *sCell = hqP->hqE->cell;
2822 RgSchEmtcDlSf *emtcSf;
2823 CmLteTimingInfo frm = timingInfo;
2826 TRC2(rgSCHDhmPrcFdbkForTb)
2829 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2832 /* Fix : syed MultiUe per TTI crash in TA List. */
2833 maxHqRetxReached = FALSE;
2835 /* Fix : syed Consider CW to TB mapping for Hq Feedback.
2836 * TODO: Need to enhance this in case of TM4 testing,
2837 * when cwSwap flag is considered. */
2839 RGSCHDBGINFO(inst, (rgSchPBuf(inst), "rgSCHDhmHqFdbkInd():\
2840 tbCnt=%d , isAck=%d",tbCnt,isAck));
2841 if (isAck == TFU_HQFDB_ACK)
2843 hqP->tbInfo[tbCnt].ackCount += 1; /* Ack counter */
2845 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][0]++;
2846 /* Do not update the Ul Trans Time in case of raCb */
2849 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2851 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2857 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2858 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2863 else if (isAck == TFU_HQFDB_NACK)
2865 hqP->tbInfo[tbCnt].nackCount += 1; /* Nack Counter */
2866 RGSCHDBGINFONEW(inst, (rgSchPBuf(inst), "<HARQ> HqP[%d:%d] NACKED "
2867 "ue(%d)\n", hqP->procId, tbCnt, hqP->hqE->ue->ueId));
2868 rgHqRvStats[tbCnt][hqP->tbInfo[tbCnt].dlGrnt.rv][1]++;
2869 /* Do not update the Ul Trans Time in case of raCb */
2872 sCell->tenbStats->sch.dlAckNack[tbCnt]\
2873 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2875 sCell->tenbStats->sch.dlNack[tbCnt]\
2876 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2883 rgSCHUtlHdlUlTransInd(cell, ue, timingInfo);
2885 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlAckNackCnt[tbCnt]++;
2886 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlNackCnt[tbCnt] ++;
2889 /* Added Dl TB count for NACKED data*/
2891 if(hqP->tbInfo[tbCnt].txCntr == 1)
2893 cell->dlUlTbCnt.tbTransDlFaulty++;
2899 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"<HARQ> HqP[%d:%d] DTXED UE(%d)\n",
2900 hqP->procId, tbCnt,hqP->hqE->ue->ueId));
2901 hqP->tbInfo[tbCnt].dtxCount += 1; /* DTX Counter*/
2904 sCell->tenbStats->sch.dlDtx[tbCnt]\
2905 [hqP->tbInfo[tbCnt].dlGrnt.rv]++;
2908 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(sCell)].dlDtxCnt[tbCnt]++;
2913 /* Added Dl TB count for DTXED data*/
2915 if(hqP->tbInfo[tbCnt].txCntr == 1)
2917 cell->dlUlTbCnt.tbTransDlFaulty++;
2922 /* Check if this is repeating UE */
2923 if (hqP->tbInfo[tbCnt].fbkRepCntr != 0)
2925 if((rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,&isAck)) != ROK)
2932 /* For a Normal UE take the decision here */
2933 hqP->tbInfo[tbCnt].isAckNackDtx = isAck;
2935 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, FALSE);
2938 /* Process either the ACK received or max retries have occurred */
2939 /* Assuming for Repetition that 2 ACKs and 2 NACKs make an NACK */
2940 if (TFU_HQFDB_ACK == isAck)
2944 /* SR_RACH_STATS : MSG4 ACK*/
2949 raCb = rgSCHDbmGetRaCb(cell, rnti);
2951 RGSCHDBGINFO(cell->instIdx,
2952 (rgSchPBuf(cell->instIdx), "Ack Rcvd. FdbkInd for Msg4Done\n"));
2953 /* Inform Random Access Module regarding the ack received */
2956 /*RRC Connection Setup failure issue where RRC connection
2957 * setup was not reaching UE due to message 4 HARQ failure */
2958 printf("\nMSG4 Ack ,calling rgSCHRamMsg4Done\n");
2959 ret = rgSCHRamMsg4Done(cell, raCb);
2964 printf("\nraCb is NULLP\n");
2967 else /*ccpu00114124- HARQ Release for Msg4 */
2969 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2970 /* Push this harq process back to the free queue */
2971 ueDl->mimoInfo.cwInfo[tbCnt].ackCnt++;
2973 if(hqP->tbInfo[tbCnt].txCntr == 1)
2975 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2978 RGSCH_NULL_CHECK(cell->instIdx, ue);
2979 RG_UPD_ACQI_TRIG_WT(ue, sCell,isAck);
2980 rgSCHDhmRlsHqpTb(hqP, tbCnt, TRUE);
2989 RGSCH_NULL_CHECK(cell->instIdx, ueDl);
2990 ueDl->mimoInfo.cwInfo[tbCnt].nackCnt++;
2992 if(hqP->tbInfo[tbCnt].txCntr == 1)
2994 rgSCHDhmUpdateAckNackHistory(sCell, ue, isAck, tbCnt);
2997 RGSCH_NULL_CHECK(cell->instIdx, ue);
2998 RG_UPD_ACQI_TRIG_WT(ue, sCell, isAck);
3002 #ifdef XEON_SPECIFIC_CHANGES
3003 CM_LOG_DEBUG(CM_LOG_ID_SCH,"Msg4 Harq FAILURE for UE(%d)\n", rnti);
3007 rgSCHDhmHqTbTrnsFail(cell, hqP, tbCnt, &hqRls);
3008 maxHqRetxReached = hqRls;
3014 /* MS_WORKAROUND: to increase Harq Fail Counter .
3015 The status field is required for tracking the number of harq faliures at MAC*/
3018 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3019 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = TRUE;
3022 else if(maxHqRetxReached)
3024 /* this is to differentiat the NACK with data loss used for UU loss L2 meas */
3025 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3026 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS; */
3031 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].status[\
3032 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = FALSE;
3034 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[\
3035 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs] = tbCnt + 1;
3036 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs++;
3040 if (hqFreed == FALSE && hqP->tbInfo[tbCnt].taSnt == TRUE)
3042 rgSCHDhmFdbkIndHndlTa(hqP, tbCnt, isAck, maxHqRetxReached);
3045 } /* rgSCHDhmPrcFdbkForTb */
3046 /** * @brief Function to decode the position of HarqFb for eachCell.
3050 * Function : rgSchGetHqFdbkPos
3052 * @param[in] RgSchCellCb *cell,
3053 * @param[in] RgSchUeCb *ue,
3054 * @param[in] RgSchDlHqProcCb *hqP,
3055 * @param[in] RgrSchFrmt1b3TypEnum uciFrmtTyp,
3056 * @param[in] Bool *isAck,
3057 * @param[in] RgTfuHqInfo *fdbk,
3061 PUBLIC Void rgSchGetHqFdbkPos
3065 RgSchDlHqProcCb *hqP,
3066 RgrSchFrmt1b3TypEnum uciFrmtTyp,
3071 PUBLIC Void rgSchGetHqFdbkPos(cell,ue,hqP,uciFrmtTyp,isAck,fdbk)
3074 RgSchDlHqProcCb *hqP;
3075 RgrSchFrmt1b3TypEnum uciFrmtTyp;
3080 if(uciFrmtTyp != RG_SCH_UCI_FORMAT1B_CS)
3082 isAck[0] = fdbk->isAck[0];
3083 isAck[1] = fdbk->isAck[1];
3087 /* LAA Making all ack for LAA CELL */
3088 //if (hqP->hqE && rgSCHLaaSCellEnabled(hqP->hqE->cell))
3098 /* PUSCH:: Fdbks are in the increasing order
3099 * of servCellIdx as per 36.212 section 5.2.26*/
3100 switch(ue->f1bCsAVal)
3102 case RG_SCH_A_VAL_2:
3104 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3106 isAck[0] = fdbk->isAck[1];/*SCell*/
3107 isAck[1] = fdbk->isAck[1];/*SCell*/
3111 isAck[0] = fdbk->isAck[0];/*PCell*/
3112 isAck[1] = fdbk->isAck[0];/*PCell*/
3116 case RG_SCH_A_VAL_3:
3118 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3121 U8 servCellIdx = rgSchUtlGetServCellIdx(hqP->hqE->cell->instIdx,
3122 hqP->hqE->cell->cellId,
3125 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[servCellIdx]->txMode.txModeEnum) > 1)
3127 if(rgSCHUtlGetMaxTbSupp(ue->cellInfo[RGSCH_PCELL_INDEX]->txMode.txModeEnum) > 1)
3129 { /* Sec cell is in mimo mode */
3130 /* use 0 and 1 for sec in case of pucch
3131 * and 1 and 2 in case of PUSCH as the primary cell is in
3132 * siso case as A =3 */
3135 isAck[0] = fdbk->isAck[0];
3136 isAck[1] = fdbk->isAck[1];
3138 {/* PUSCH as per 36.212 serction 5.2.26*/
3139 isAck[0] = fdbk->isAck[1];
3140 isAck[1] = fdbk->isAck[2];
3143 {/* sec cell is in siso */
3144 isAck[0] = fdbk->isAck[2];
3148 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3149 {/* primay cell is in mimo
3151 isAck[0] = fdbk->isAck[0];
3152 isAck[1] = fdbk->isAck[1];
3157 isAck[0] = fdbk->isAck[2];
3159 {/* PUSCH as per 36.212 serction 5.2.26*/
3160 isAck[0] = fdbk->isAck[0];
3166 case RG_SCH_A_VAL_4:
3168 if(RG_SCH_IS_CELL_SEC(ue,hqP->hqE->cell))
3170 isAck[0] = fdbk->isAck[2];
3171 isAck[1] = fdbk->isAck[3];
3174 if(isAck[0] == TFU_HQFDB_ACK)
3176 gSCellTb1AckCount++;
3177 }else if(isAck[0] == TFU_HQFDB_NACK)
3179 gSCellTb1NackCount++;
3182 gSCellTb1DtxCount++;
3185 if(isAck[1] == TFU_HQFDB_ACK)
3187 gSCellTb2AckCount++;
3188 }else if(isAck[1] == TFU_HQFDB_NACK)
3190 gSCellTb2NackCount++;
3193 gSCellTb2DtxCount++;
3201 isAck[0] = fdbk->isAck[0];
3202 isAck[1] = fdbk->isAck[1];
3205 if(isAck[0] == TFU_HQFDB_ACK)
3207 gPCellTb1AckCount++;
3208 }else if(isAck[0] == TFU_HQFDB_NACK)
3210 gPCellTb1NackCount++;
3213 gPCellTb1DtxCount++;
3216 if(isAck[1] == TFU_HQFDB_ACK)
3218 gPCellTb2AckCount++;
3219 }else if(isAck[1] == TFU_HQFDB_NACK)
3221 gPCellTb2NackCount++;
3224 gPCellTb2DtxCount++;
3239 }/* End of rgSchGetHqFdbkPos */
3242 PUBLIC Void rgSchGetHqFdbkPosFormat3
3244 RgSchDlHqProcCb *hqP,
3249 PUBLIC Void rgSchGetHqFdbkPosFormat3(hqP,isAck,fdbk)
3250 RgSchDlHqProcCb *hqP;
3255 U8 cellIdx = RG_SCH_CMN_GET_CELL_IDX_FROM_HQP(hqP);
3256 isAck[0] = (U8)fdbk[cellIdx];
3257 isAck[1] = (U8)fdbk[cellIdx + 1];
3260 /** * @brief Handler for HARQ feedback received for DL transmission.
3264 * Function : rgSCHDhm5gtfHqFdbkInd
3266 * This function shall act on the feedback received from TOM for DL
3267 * transmission. If the feedback for msg4 is final (after max transmissions
3268 * or ACK) inform RAM that Msg4 transmission is done.
3271 * @param[in] Void *cb
3272 * @param[in] U8 cbType
3273 * @param[in] RgSchCellCb *cell
3274 * @param[in] RgTfuHarqAckIndInfo *fdbk
3275 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3276 * @param[in] RgSchErrInfo *err
3282 PUBLIC S16 rgSCHDhm5gtfHqFdbkInd
3286 CmLteTimingInfo timingInfo,
3291 PUBLIC S16 rgSCHDhm5gtfHqFdbkInd(ue, cell, timingInfo, fdbk, err)
3294 CmLteTimingInfo timingInfo;
3299 RgSchDlHqProcCb *hqP = NULLP;
3300 CmLList *node = NULLP;
3304 Bool isMsg4 = FALSE;
3308 RgInfRlsHqInfo *rlsHqBufs = NULLP;
3310 TRC2(rgSCHDhm5gtfHqFdbkInd)
3312 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3314 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3316 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3318 hqPCount = lnk->count;
3323 hqP = (RgSchDlHqProcCb *)node->node;
3325 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3326 procId = hqP->procId;
3328 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3330 if (HQ_TB_WAITING == hqP->tbInfo[0].state)
3332 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, 0,
3333 timingInfo, fdbk, rlsHqBufs, err);
3335 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3337 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3338 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3340 rlsHqBufs->numUes++;
3346 } /* rgSCHDhm5gtfHqFdbkInd */
3348 /** * @brief Handler for HARQ feedback received for DL transmission.
3352 * Function : rgSCHDhmHqFdbkInd
3354 * This function shall act on the feedback received from TOM for DL
3355 * transmission. If the feedback for msg4 is final (after max transmissions
3356 * or ACK) inform RAM that Msg4 transmission is done.
3359 * @param[in] Void *cb
3360 * @param[in] U8 cbType
3361 * @param[in] RgSchCellCb *cell
3362 * @param[in] RgTfuHarqAckIndInfo *fdbk
3363 * @param[in] RgInfRlsHqInfo *rlsHqBufs
3364 * @param[in] RgSchErrInfo *err
3370 PUBLIC S16 rgSCHDhmHqFdbkInd
3375 CmLteTimingInfo timingInfo,
3377 RgInfRlsHqInfo *rlsHqBufs,
3381 PUBLIC S16 rgSCHDhmHqFdbkInd(cb, cbType, cell, timingInfo, fdbk, rlsHqBufs, err)
3385 CmLteTimingInfo timingInfo;
3387 RgInfRlsHqInfo *rlsHqBufs;
3391 RgSchDlHqTbCb *tbCb;
3392 RgSchDlHqEnt *hqE = NULLP;
3393 RgSchDlHqProcCb *hqP = NULLP;
3394 CmLList *node = NULLP;
3396 /* Create and Initialize Ue it so that Its not Deferenced Unnecessarily */
3397 RgSchUeCb *ue = NULLP;
3401 Bool isMsg4 = FALSE;
3402 RgSchRaCb *raCb = NULLP;
3404 /* Added Insure Fixes Of UR.Initialized procId */
3406 /* DTX Change: Bool is converted into U8*/
3407 U8 isAck[2]={0}; /*Changed to Array of 2*/
3412 CmLteTimingInfo fdbkRcptTime = timingInfo;
3413 #ifdef RGSCH_SPS_STATS
3414 RgSchCmnDlHqProc *cmnHqDl;
3418 TfuHqFdbk format3Ack[CM_LTE_MAX_CELLS *2] = {0};
3420 RgrSchFrmt1b3TypEnum uciFrmtTyp = RG_SCH_UCI_FORMAT1A_1B;
3422 TRC2(rgSCHDhmHqFdbkInd)
3424 /* Get the subframe associated with the feedback */
3425 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper output
3426 * if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME() as it is
3427 * serving the purpose */
3428 RGSCHDECRFRMCRNTTIME(timingInfo, timingInfo, 4);
3430 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3431 if (cbType == RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3433 raCb = (RgSchRaCb *)(cb);
3435 hqP = rgSCHDhmHqProcByTime(hqE, timingInfo, &isMsg4,\
3441 rnti = raCb->tmpCrnti;
3445 ue = (RgSchUeCb *)(cb);
3446 hqE = RG_SCH_CMN_GET_UE_HQE(ue, cell);
3448 lnk = &ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst;
3451 hqPCount = lnk->count;
3454 uciFrmtTyp = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].uciFrmtTyp;
3459 from Harq Proc get ueCb = hqP->hqEnt->ueCb
3460 from ueCb get cmnUecb = (RgSchCmnUe *)ueCb->sch;
3461 from ueCb get dlUe = (RgSchCmnDlUe)cmnUeCb->dl
3462 from get cmInfo "RgSchCmnDlUeCwInfo" dlUe->mimoInfo->cwInfo[0]
3463 from get CQI from cmInfo->cqi
3464 from cmInfo get iTbs cmInfo->iTbs[0]
3465 call RG_SCH_CMN_DL_TBS_TO_MCS to map iTbs=>MCS
3466 Update stats in cellCb
3467 cellCb->hqFailStats[cmInfo->cqi].mcs = RG_SCH_CMN_DL_TBS_TO_MCS(cmInfo->iTbs[0]);
3468 if (fdbk->isAck == TRUE)
3469 cellCb->hqFailStats[cmInfo->cqi].numOfNacks += 1;
3471 cellCb->hqFailStats[cmInfo->cqi].numOfAcks += 1;
3472 DL Ack/Nack statistics
3474 #ifdef MAC_SCH_STATS
3475 if (hqE->ue != NULLP)
3477 RgSchUeCb *ueCb = hqE->ue;
3478 RgSchCmnUe *cmnUe = (RgSchCmnUe*)ueCb->sch;
3479 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ueCb,hqE->cell);/*CA dev*/
3480 U8 tbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
3481 static U32 retxCnt = 0;
3483 if (fdbk->isAck[0] == TFU_HQFDB_ACK)
3485 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfAcks++;
3490 hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].numOfNacks++;
3492 RG_SCH_CMN_DL_TBS_TO_MCS(tbs,
3493 (hqFailStats.dlCqiStat[(dlUe->mimoInfo.cwInfo[0].cqi - 1)].mcs));
3495 #endif /* MAC_SCH_STATS */
3497 /* Fetch the harqProc from the inUse list */
3499 /* Check if the feedback timing matches with ue->relPdcchFbkTiming*/
3500 /* Call Common module with the feedback information */
3501 if (ue && (ue->relPdcchFbkTiming.sfn != (RGSCH_MAX_SFN + 1)))
3503 if (RGSCH_TIMEINFO_SAME(fdbkRcptTime, ue->relPdcchFbkTiming))
3505 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3508 if(uciFrmtTyp == RG_SCH_UCI_FORMAT1B_CS)
3509 {/* Feedback for SPS Release on PCell
3510 If Pcell is in mimo, feedback index will be 0
3512 if(rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode) > 1)
3514 isAck[0] = fdbk->isAck[0];
3517 isAck[0] = fdbk->isAck[2];
3520 /* Not releasing pdcch here
3521 * as it is already done at the time of
3523 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3530 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,
3531 "CRNTI:%d NO HARQ proc available for feedback: TimingInfo: "
3532 "sfn %d subframe %d", ue->ueId, timingInfo.sfn,
3533 timingInfo.subframe);
3537 isAck[0] = fdbk->isAck[0];
3538 /* Note: Since relPdcchFbkTimimg matches with the recieved
3539 * feedback, assumed that feedback is for release PDCCH */
3540 rgSCHUtlDlRelPdcchFbk(cell, ue, isAck[0]);
3542 /* Remove release PDCCH from the subframe */
3543 rgSCHUtlPdcchPut(cell, &sf->pdcchInfo, sf->relPdcch);
3544 sf->relPdcch = NULLP;
3549 #endif /* LTEMAC_SPS */
3551 /* Remove the harq process from the subframe */
3552 sf = rgSCHUtlSubFrmGet(cell, timingInfo);
3553 RG_SCH_ADD_TO_CRNT_TIME(timingInfo, timingInfo, 1);
3566 if(cbType != RGSCH_HQ_FDB_IND_CB_TYPE_RA_CB)
3568 hqP = (RgSchDlHqProcCb *)node->node;
3570 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3572 procId = hqP->procId;
3574 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3576 /*Get the position of Ack/Nack from 2 bytes fdbkInfo.
3577 * On the basis of f1bCsAVal find the position of iAck or Nack*/
3579 if (uciFrmtTyp == RG_SCH_UCI_FORMAT3)
3581 rgSchGetHqFdbkPosFormat3(hqP,isAck,format3Ack);
3586 rgSchGetHqFdbkPos(cell,ue,hqP, uciFrmtTyp, isAck,fdbk);
3588 for (tbCnt = 0; tbCnt < 2; tbCnt++)
3590 if (HQ_TB_WAITING == hqP->tbInfo[tbCnt].state)
3592 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCnt,
3593 timingInfo, isAck[tbCnt], rlsHqBufs, err);
3596 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3598 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3599 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3601 rlsHqBufs->numUes++;
3606 node = sf->ackNakRepQ.first;
3609 tbCb = (RgSchDlHqTbCb *)(node->node);
3612 procId = hqP->procId;
3613 rlsHqBufs = &(hqP->hqE->cell->rlsHqArr[hqP->hqE->cell->crntHqIdx]);
3614 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 0;
3615 if (HQ_TB_WAITING == tbCb->state)
3617 isAck[0] = fdbk->isAck[tbCb->tbIdx];
3618 rgSCHDhmPrcFdbkForTb(cell, ue, hqP, sf, isMsg4, rnti, tbCb->tbIdx,
3619 timingInfo, isAck[0], rlsHqBufs, err);
3621 hqP->cwSwpEnabled = FALSE;
3622 if(rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs)
3624 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = rnti;
3625 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId =
3627 rlsHqBufs->numUes++;
3634 } /* rgSCHDhmHqFdbkInd */
3635 #endif /* LTE_FDD */
3639 * @brief Handler for Harq related UE configuration.
3643 * Function : rgSCHDhmRgrUeCfg
3645 * This function shall fetch the harq related information into the
3646 * respective ueCb from the UE configuration as provided by the
3649 * @param[in] RgSchCellCb *cell
3650 * @param[in] RgSchUeCb *ueCb
3651 * @param[in] RgrUeCfg *ueCfg
3652 * @param[out] RgSchErrInfo *err
3658 PUBLIC Void rgSCHDhmRgrUeCfg
3666 PUBLIC Void rgSCHDhmRgrUeCfg(cell, ueCb, ueCfg, err)
3673 TRC2(rgSCHDhmRgrUeCfg)
3677 /* Initialize the TA Timer */
3678 cmInitTimers(&ueCb->taTmr, 1);
3680 /* Setting these values irrespective of taTmr value */
3681 ueCb->dl.taCb.state = RGSCH_TA_IDLE;
3682 /* Corrected default value of TA as per 36.213, 4.2.3 */
3683 ueCb->dl.taCb.ta = RGSCH_NO_TA_RQD;
3685 /*[ccpu00121813]-ADD-Initializing outstanding TA value */
3686 ueCb->dl.taCb.outStndngTa = FALSE;
3687 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
3689 /* Start TA timer only if cfgd as FINITE value */
3690 if (ueCfg->ueTaTmrCfg.pres)
3692 /* Configuring taTmr with 30 deficit, to enable eNodeB sending
3693 * TA command before the expiry of TA at UE. Also considering for
3694 * possible retx for this TA command */
3695 /*[ccpu00121813]-ADD-Added chk if tatmr val > 30 */
3696 if(ueCfg->ueTaTmrCfg.taTmr > 30)
3698 ueCb->dl.taCb.cfgTaTmr = ueCfg->ueTaTmrCfg.taTmr - 30;
3700 rgSCHTmrStartTmr (cell, ueCb, RG_SCH_TMR_TA, ueCb->dl.taCb.cfgTaTmr);
3703 } /* rgSCHDhmRgrUeCfg */
3707 * @brief Handler for HARQ related UE Reconfiguration
3711 * Function : rgSCHDhmRgrCellCfg
3713 * This function shall fetch the HARQ related information into the
3714 * respective ueCb from the UE configuration as provided by the
3717 * @param[in] RgSchCellCb *cell
3718 * @param[in] RgrCellCfg *cellCfg
3719 * @param[out] RgSchErrInfo *err
3726 PUBLIC Void rgSCHDhmRgrCellCfg
3729 RgrCellCfg *cellCfg,
3733 PUBLIC Void rgSCHDhmRgrCellCfg(cell, cellCfg, err)
3735 RgrCellCfg *cellCfg;
3740 PTR pUeCb;/* previous UE Control block */
3741 PTR nUeCb;/* next UE control block */
3745 TRC2(rgSCHDhmRgrCellCfg)
3751 cell->dlHqCfg = cellCfg->dlHqCfg;
3754 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3762 /* Update the DL Harq related information */
3763 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3764 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3767 /* Initializing the list for ueCbs that would have ta */
3768 cmLListInit(&cell->taUeLst);
3770 cmLListInit(&cell->ccchSduUeLst);
3771 cmLListInit(&cell->contResGrdTmrLst);
3772 cmLListInit(&cell->contResTmrLst);
3774 if(cell->emtcEnable)
3776 rgSCHDhmEmtcRgrCellCfg(cell);
3781 /* Initializing the timer queue */
3782 cell->tqCp.nxtEnt = 0;
3783 cell->tqCp.tmrLen = RGSCH_UE_TQ_SIZE;
3785 for (idx = 0; idx < RGSCH_UE_TQ_SIZE; idx++)
3787 cell->tq[idx].first = NULLP;
3788 cell->tq[idx].tail = NULLP;
3791 } /* rgSCHDhmRgrCellCfg */
3794 * @brief Handler for Updating HARQ Information from Cell Reconfiguration
3798 * Function : rgSCHDhmRgrCellRecfg
3800 * This function shall fetch the HARQ related information into the
3801 * respective ueCb from the UE configuration as provided by the
3804 * @param[in] RgSchCellCb *cell
3805 * @param[in] RgrCellRecfg *cellRecfg
3806 * @param[out] RgSchErrInfo *err
3813 PUBLIC Void rgSCHDhmRgrCellRecfg
3816 RgrCellRecfg *cellRecfg,
3820 PUBLIC Void rgSCHDhmRgrCellRecfg(cell, cellRecfg, err)
3822 RgrCellRecfg *cellRecfg;
3827 PTR pUeCb;/* previous UE Control block */
3828 PTR nUeCb;/* next UE control block */
3831 TRC2(rgSCHDhmRgrCellRecfg)
3837 /* Update the cell with recieved configuration */
3838 if (cellRecfg->recfgTypes & RGR_CELL_DL_HARQ_RECFG)
3840 cell->dlHqCfg = cellRecfg->dlHqRecfg;
3844 ret = cmHashListGetNext(&(cell->ueLst), pUeCb, &nUeCb);
3852 /* Update the DL Harq related information */
3853 hqE = RG_SCH_CMN_GET_UE_HQE(((RgSchUeCb*)nUeCb), cell);
3854 hqE->maxHqTx = cell->dlHqCfg.maxDlHqTx;
3859 } /* rgSCHDhmRgrCellRecfg */
3862 * @brief Handler for freeing up the HARQ related information from ueCb
3866 * Function : rgSCHDhmFreeUe
3868 * This function shall free up the HARQ specific information from ueCb.
3870 * @param[in] RgSchUeCb *ueCb
3876 PUBLIC Void rgSCHDhmFreeUe
3881 PUBLIC Void rgSCHDhmFreeUe(ueCb)
3886 TRC2(rgSCHDhmFreeUe)
3888 /* If TA Timer is running. Stop it */
3889 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3891 rgSCHTmrStopTmr(ueCb->cell, ueCb->taTmr.tmrEvnt, ueCb);
3894 /* ccpu00118357 - ADD - stop the periodic BSR timer so it
3895 * doesn't expire after UE is deleted */
3897 if (ueCb->bsrTmr.tmrEvnt != TMR_NONE)
3899 rgSCHTmrStopTmr(ueCb->cell, ueCb->bsrTmr.tmrEvnt, ueCb);
3901 #endif /* ifdef RGR_V1*/
3904 if (RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell))
3906 rgSCHDhmDelHqEnt(ueCb->cell, &(RG_SCH_CMN_GET_UE_HQE(ueCb, ueCb->cell)));
3909 /* This UE needs to be removed from its entry into cell's taUeLst */
3910 /*Fix for ccpu00113622 - Delete Only when taLnk Node exists*/
3911 if(ueCb->taLnk.node)
3913 cmLListDelFrm(&(ueCb->cell->taUeLst), &ueCb->taLnk);
3914 ueCb->taLnk.node = NULLP;
3917 if (ueCb->dlTaLnk.node != NULLP)
3919 /* Fix: syed Need to raise a CR for not calling CMN or specific scheduler
3920 * function directly from other modules. APIs should be defined and/or used
3921 * instead. Please check for other possible incorrect usage. */
3922 rgSCHCmnRmvFrmTaLst(ueCb->cell, ueCb);
3927 } /* rgSCHDhmFreeUe */
3930 * @brief Handler for updating the TA.
3934 * Function : rgSCHDhmUpdTa
3936 * This function shall update the TA received.
3938 * @param[in] RgSchCellCb *cell
3939 * @param[in] RgSchUeCb *ueCb
3946 PUBLIC Void rgSCHDhmUpdTa
3953 PUBLIC Void rgSCHDhmUpdTa(cell, ueCb, ta)
3961 if (ueCb->dl.taCb.state == RGSCH_TA_IDLE)
3963 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
3964 ueCb->dl.taCb.numRemSf = 2;
3965 rgSCHUtlDlTARpt(cell, ueCb);
3966 /* If TA Timer is running. Stop it */
3967 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
3969 rgSCHTmrStopTmr(cell, ueCb->taTmr.tmrEvnt, ueCb);
3972 /* SR_RACH_STATS : TA MODIFIED */
3973 if (ueCb->dl.taCb.ta != ta)
3977 ueCb->dl.taCb.ta = ta;
3981 /* [ccpu00121813]-ADD-Updating outstanding values
3982 * TA which gets transmitted at N gets applied at UE at N+6,once TA
3983 * has been scheduled,further TA values get stored in outstndngTaval.
3984 * Once TA gets applied at UE or when NACK/DTX is rcvd for maxhqretx times
3985 * then schedule the outstanding TA val if present */
3986 ueCb->dl.taCb.outStndngTa = TRUE;
3987 ueCb->dl.taCb.outStndngTaval = ta;
3991 } /* rgSCHDhmUpdTa */
3993 /** @brief This function handles the TA timer expiry.
3997 * Function: This function handled the TA Expiry.
4003 * @param[in] RgSchUeCb *ueCb
4009 PUBLIC Void rgSCHDhmProcTAExp
4014 PUBLIC Void rgSCHDhmProcTAExp (ueCb)
4018 TRC2(rgSCHDhmProcTAExp);
4020 /* Ask scheduler to schedule this UE */
4021 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
4022 rgSCHUtlDlTARpt(ueCb->cell, ueCb);
4024 } /* end of rgSCHDhmProcTAExp */
4026 /* 3.1 MIMO: LC details at TB level rather than Hq Level */
4028 * @brief Handler for Adding scheduled logical channel data information
4033 * Function : rgSCHDhmAddLcData
4035 * This function shall add the scheduled logical channel data
4036 * information to the HARQ process.
4038 * @param[in] RgSchLchAllocInfo *lchData
4039 * @param[in] RgSchDlHqTbCb *tbInfo
4045 PUBLIC S16 rgSCHDhmAddLcData
4048 RgSchLchAllocInfo *lchData,
4049 RgSchDlHqTbCb *tbInfo
4052 PUBLIC S16 rgSCHDhmAddLcData(inst, lchData, tbInfo)
4054 RgSchLchAllocInfo *lchData;
4055 RgSchDlHqTbCb *tbInfo;
4059 TRC2(rgSCHDhmAddLcData)
4061 if(tbInfo->numLch >= RGSCH_MAX_NUM_DED_LC)
4066 tbInfo->lchSchdDataArr[tbInfo->numLch] = *lchData;
4072 } /* rgSCHDhmAddLcData */
4076 * @brief Handler for releaseing the subframe allocation.
4080 * Function : rgSCHDhmTddRlsSubFrm
4082 * This function shall be invoked to release the DL Sf
4083 * allocations for which HARQ feedback time has expired.
4085 * @param[in] RgSchCellCb *cellCb
4086 * @param[in] CmLteTimingInfo uciTimingInfo;
4092 PUBLIC S16 rgSCHDhmTddRlsSubFrm
4094 RgSchCellCb *cellCb,
4095 CmLteTimingInfo uciTimingInfo
4098 PUBLIC S16 rgSCHDhmTddRlsSubFrm(cellCb, uciTimingInfo)
4099 RgSchCellCb *cellCb;
4100 CmLteTimingInfo uciTimingInfo;
4103 CmLteTimingInfo dlSfTime;
4104 RgSchTddDlAscSetIdxK ascIdx;
4108 TRC2(rgSCHDhmTddRlsSubFrm)
4111 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.subframe];
4112 noFdbks = ascIdx.numFdbkSubfrms;
4113 for(i=0; i < noFdbks; i++)
4115 /* Get the subframe and sfn for which HARQ Ack/Nack
4117 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4118 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4119 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4120 * as it is serving the purpose */
4121 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4122 rgSCHUtlDlRlsSubFrm(cellCb, dlSfTime);
4125 }/* rgSCHDhmTddRlsSubFrm */
4131 * @brief Handler for Removing the HARQ process from a dlsf.
4135 * Function : rgSCHDhmRlsDlsfHqProc
4137 * This function shall be invoked for every tti. It goes back to
4138 * to the sixth last subframe to check whether it still exists. If
4139 * that exists this function traverses through the entire harq
4140 * proc list associated and frees up all of them.
4142 * @param[in] RgSchCellCb *cellCb
4143 * @param[in] CmLteTimingInfo timingInfo
4149 PUBLIC S16 rgSCHDhmRlsDlsfHqProc
4151 RgSchCellCb *cellCb,
4152 CmLteTimingInfo uciTimingInfo
4155 PUBLIC S16 rgSCHDhmRlsDlsfHqProc(cellCb, uciTimingInfo)
4156 RgSchCellCb *cellCb;
4157 CmLteTimingInfo uciTimingInfo;
4161 CmLteTimingInfo dlSfTime;
4162 CmLteTimingInfo nxtfrm = {0,0};
4163 RgSchDlHqProcCb *tmpHqProc;
4164 RgSchTddDlAscSetIdxK ascIdx;
4167 RgSchDlSf *nxtDlsf = NULLP;
4171 /*ccpu00130018 -MOD -Initiatizing with FALSE*/
4173 RgSchTddANInfo *anInfo = NULLP;
4174 RgSchDlHqTbCb *tbCb;
4175 RgSchUeCb *ue = NULLP;
4176 TRC2(rgSCHDhmRlsDlsfHqProc)
4179 rgSchTddDlAscSetIdxKTbl[cellCb->ulDlCfgIdx][uciTimingInfo.subframe];
4180 noFdbks = ascIdx.numFdbkSubfrms;
4181 for(i=0; i < noFdbks; i++)
4183 /* Get the subframe and sfn for which HARQ Ack/Nack
4185 /* ccpu00132341-MOD- optimized getting DLSF time using macro*/
4186 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4187 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4188 * as it is serving the purpose */
4189 RGSCHDECRFRMCRNTTIME(uciTimingInfo, dlSfTime, ascIdx.subfrmNum[i]);
4191 dlSf = rgSCHUtlSubFrmGet (cellCb, dlSfTime);
4192 if(cellCb->ulDlCfgIdx != 5)
4194 rgSCHUtlGetNxtDlSfInfo(dlSfTime, cellCb, dlSf, &nxtDlsf, &nxtfrm);
4196 /* Subframe is present. Delete all the harq associations from
4200 /*Handling for Msg4*/
4201 node = dlSf->msg4HqPLst.first;
4204 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4206 tmpHqProc->cwSwpEnabled = FALSE;
4207 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4209 tbCb = &tmpHqProc->tbInfo[0];
4211 /* Fix : syed MultiUe per TTI crash in TA List. */
4215 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4218 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4220 /* Delete the Harq Association. Release the Harq Process */
4221 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4223 if (tbCb->taSnt == TRUE)
4225 /* [ccpu00127148] Correcting the check */
4226 if (TRUE == maxRetx)
4228 tbCb->taSnt = FALSE;
4229 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4230 ue->dl.taCb.state = RGSCH_TA_IDLE;
4232 rgSCHUtlReTxTa(cellCb, ue);
4238 node = dlSf->ueLst.first;
4244 ue = (RgSchUeCb *)(node->node);
4248 hqPNode = ue->dl.dlSfHqInfo[cellCb->cellId][dlSf->dlIdx].hqPLst.first;
4251 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4252 hqPNode = hqPNode->next;
4253 for (idx = 0 ;idx < 2; idx++)
4255 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4257 tbCb = &tmpHqProc->tbInfo[idx];
4259 /* Fix : syed MultiUe per TTI crash in TA List. */
4263 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4266 /* Update feedback time for this process so that
4267 * next subframe its picked up */
4269 U8 servCellIdx = rgSchUtlGetServCellIdx(
4270 tmpHqProc->hqE->cell->instIdx,
4271 tmpHqProc->hqE->cell->cellId,
4273 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4275 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,RGSCH_PCELL_INDEX);
4279 RGSCHDBGERR(cellCb->instIdx, (rgSchPBuf(cellCb->instIdx),
4280 "Ack/Nack Info is NULL, Processing %dth feedback subframe for DTX"
4281 "received on SFN [%d] and SF [%d]\n",i, uciTimingInfo.sfn,
4282 uciTimingInfo.subframe));
4284 else if (tbCb->fbkRepCntr == 0)
4286 /* Initialise the Ack/Nack feedback */
4288 if(!(anInfo->dlDai))
4290 rgSCHUtlInitUeANFdbkInfo(anInfo);
4295 /* Update feedback time for this process so that
4296 * * next subframe its picked up */
4297 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4298 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4299 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4300 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, TRUE);
4305 rgSCHUtlDlHqPTbRmvFrmTx(dlSf, tmpHqProc, tbCb->tbIdx, FALSE);
4306 /*ccpu000119494-ADD- for SPS, call SPS specific DTX handler */
4309 /* Delete the Harq Association. Release the Harq Process */
4310 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4312 if (tbCb->taSnt == TRUE)
4314 /* [ccpu00127148] Correcting the check */
4315 if (TRUE == maxRetx)
4317 tbCb->taSnt = FALSE;
4318 RGSCH_NULL_CHECK(cellCb->instIdx, ue)
4319 ue->dl.taCb.state = RGSCH_TA_IDLE;
4321 rgSCHUtlReTxTa(cellCb, ue);
4323 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4324 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4333 node = dlSf->ackNakRepQ.first;
4336 tbCb = (RgSchDlHqTbCb *)(node->node);
4337 tmpHqProc = tbCb->hqP;
4338 /* [ccpu00121813]-ADD-Fetch ueCb */
4339 ue = tmpHqProc->hqE->ue;
4340 /* Fix : syed MultiUe per TTI crash in TA List. */
4345 tmpHqProc->hqE->cell->tenbStats->sch.dlDtx[tbCb->tbIdx][tbCb->dlGrnt.rv]++;
4346 ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(tmpHqProc->hqE->cell)].dlDtxCnt[tbCb->tbIdx] ++;
4350 /* If This is not the last repetition */
4351 if (tbCb->fbkRepCntr > 1)
4353 /* Update feedback time for this process so that
4354 * next subframe its picked up */
4356 U8 servCellIdx = rgSchUtlGetServCellIdx(
4357 tmpHqProc->hqE->cell->instIdx,
4358 tmpHqProc->hqE->cell->cellId,
4360 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,servCellIdx);
4362 anInfo = rgSCHUtlGetUeANFdbkInfo(ue, &tbCb->fdbkTime,0);
4368 RGSCH_NULL_CHECK(cellCb->instIdx, nxtDlsf);
4369 RGSCH_UPD_HQAN_FDBKTIME(tbCb, nxtDlsf, nxtfrm);
4370 RGSCH_UPD_ANINFO_WITH_HQ(anInfo, tbCb);
4371 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4377 rgSCHUtlDlHqPTbRmvFrmTx(dlSf,tmpHqProc,tbCb->tbIdx, TRUE);
4379 if (((tbCb->nackCount + tbCb->dtxCount) >= tbCb->ackCount))
4381 /*even if one NACK, we consider the feedback
4382 * on a whole as NACk */
4383 if ( tbCb->nackCount != 0 )
4385 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4389 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4393 /* Delete the Harq Association. Release the Harq Process */
4394 rgSCHDhmHqTbTrnsFail(cellCb, tmpHqProc, tbCb->tbIdx, &maxRetx);
4396 }/*if(((tbCb->nackCount+....*/
4399 if (tbCb->taSnt == TRUE)
4401 /* [ccpu00127148] Correcting the check */
4402 if (TRUE == maxRetx)
4404 tbCb->taSnt = FALSE;
4405 ue->dl.taCb.state = RGSCH_TA_IDLE;
4407 rgSCHUtlReTxTa(cellCb, ue);
4408 RLOG_ARG0(L_DEBUG,DBG_CELLID,cellCb->cellId,
4409 "Nack/DTX Rcvd for TA. Max Tries Attempted");
4416 }/* rgSCHDhmRlsDlsfHqProc */
4417 #else /* ifdef LTE_TDD */
4419 * @brief Handler for Removing the HARQ process from a dlsf.
4423 * Function : rgSCHDhmRlsDlsfHqProc
4425 * This function shall be invoked for every tti. It goes back to
4426 * to the sixth last subframe to check whether it still exists. If
4427 * that exists this function traverses through the entire harq
4428 * proc list associated and frees up all of them.
4430 * @param[in] RgSchCellCb *cell
4436 PUBLIC S16 rgSCHDhmRlsDlsfHqProc
4439 CmLteTimingInfo timingInfo
4442 PUBLIC S16 rgSCHDhmRlsDlsfHqProc(cell, timingInfo)
4444 CmLteTimingInfo timingInfo;
4448 CmLteTimingInfo frm;
4449 RgSchDlHqProcCb *tmpHqProc;
4454 RgSchDlHqTbCb *tbCb;
4457 TRC2(rgSCHDhmRlsDlsfHqProc)
4459 /* Fetch the current timing info. Modify it to Last sf to be rlsd.*/
4460 /* ccpu00133109: Removed RGSCHSUBFRMCRNTTIME as it is not giving proper
4461 * output if diff is more than 10. Instead using RGSCHDECRFRMCRNTTIME()
4462 * as it is serving the purpose */
4463 RGSCHDECRFRMCRNTTIME(timingInfo, frm, RG_SCH_CMN_HARQ_INTERVAL);
4466 /* Get the required Last subframe */
4467 sf = rgSCHUtlSubFrmGet(cell, frm);
4470 /*Handling for Msg4*/
4471 node = sf->msg4HqPLst.first;
4474 tmpHqProc = (RgSchDlHqProcCb *)(node->node);
4475 if (HQ_TB_WAITING == tmpHqProc->tbInfo[0].state)
4477 tbCb = &tmpHqProc->tbInfo[0];
4478 /* Fix : syed MultiUe per TTI crash in TA List. */
4481 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4482 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4485 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4486 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4488 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4493 if (tbCb->fbkRepCntr != 0)
4495 /* Update timingInfo for this hqP so that next subframe its picked up */
4496 RG_SCH_ADD_TO_CRNT_TIME(tbCb->timingInfo, tbCb->timingInfo, 1);
4497 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, TRUE);
4501 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,tbCb->tbIdx, FALSE);
4503 /* Delete the Harq Association. Release the Harq Process */
4504 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4508 /* Subframe is present. Delete all the harq associations from
4511 node = sf->ueLst.first;
4514 ue = (RgSchUeCb *)(node->node);
4518 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
4522 tmpHqProc = (RgSchDlHqProcCb *)hqPNode->node;
4523 tmpHqProc->cwSwpEnabled = FALSE;
4524 hqPNode = hqPNode->next;
4525 for (idx = 0 ;idx < 2; idx++)
4527 if (HQ_TB_WAITING == tmpHqProc->tbInfo[idx].state)
4529 tbCb = &tmpHqProc->tbInfo[idx];
4530 /* Fix : syed MultiUe per TTI crash in TA List. */
4533 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),"\n rgSCHDhmRlsDlsfHqProc():\
4534 txCntr=%d tmpHqProc=%d",tbCb->txCntr,tmpHqProc->procId));
4537 if ((tmpHqProc->hqE->msg4Proc == tmpHqProc) ||
4538 (tmpHqProc->hqE->ccchSduProc == tmpHqProc))
4540 tbCb->isAckNackDtx = TFU_HQFDB_NACK;
4545 tbCb->isAckNackDtx = TFU_HQFDB_DTX;
4548 rgSCHUtlDlHqPTbRmvFrmTx(sf,tmpHqProc,idx, FALSE);
4551 /* Delete the Harq Association. Release the Harq Process */
4552 rgSCHDhmHqTbTrnsFail(cell, tmpHqProc, tbCb->tbIdx, &maxRetx);
4554 if (tbCb->taSnt == TRUE)
4556 /* [ccpu00127148] Correcting the check */
4557 if (TRUE == maxRetx)
4559 tbCb->taSnt = FALSE;
4560 ue->dl.taCb.state = RGSCH_TA_IDLE;
4562 rgSCHUtlReTxTa(cell, ue);
4563 RGSCHDBGINFO(cell->instIdx, (rgSchPBuf(cell->instIdx),
4564 "Nack/DTX Rcvd for TA. Max Tries Attempted\n"));
4567 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
4568 ueDl->mimoInfo.cwInfo[tbCb->tbIdx].dtxCnt++;
4577 } /* rgSCHDhmRlsDlsfHqProc */
4582 * @brief This function marks the HARQ process with a given ID as SPS HARQ
4587 * Function: rgSCHDhmMarkSpsHqProc
4588 * Purpose: This function returns the HARQ process with the given ID.
4589 * Invoked by: SPS Module
4591 * - Get the HARQ process by index from the UE
4592 * - Set isSpsHqProc = TRUE
4594 * @param[in] RgSchUeCb *ue
4597 * -# ROK if successful
4598 * -# RFAILED otherwise
4602 PUBLIC S16 rgSCHDhmMarkSpsHqProc
4608 PUBLIC S16 rgSCHDhmMarkSpsHqProc(ue, idx)
4613 RgSchDlHqProcCb *hqP;
4614 TRC2(rgSCHDhmMarkSpsHqProc)
4616 /* Pick the proc based on the index provided */
4617 rgSCHDhmGetHqProcFrmId(ue->cell, ue, idx, &hqP);
4620 } /* rgSCHDhmMarkSpsHqProc */
4621 #endif /* RG_UNUSED */
4622 #endif /* LTEMAC_SPS */
4625 /** * @brief Handler for HARQ feedback received for DL AckNack rep enabled UE
4629 * Function : rgSCHDhmProcHqFdbkAckNackRep
4631 * This function shall act on the feedback received from TOM for DL
4635 * @param[in] RgSchDlHqProcCb *hqP
4636 * @param[in] RgSchDlSf *sf
4637 * @param[in] U8 tbCnt
4638 * @param[in] U8 *isAck
4644 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep
4646 RgSchDlHqProcCb *hqP,
4652 PRIVATE S16 rgSCHDhmProcHqFdbkAckNackRep(hqP,sf,tbCnt,isAck)
4653 RgSchDlHqProcCb *hqP;
4659 TRC2(rgSCHDhmProcHqFdbkAckNackRep)
4660 /* Check if this is repeating UE */
4661 rgSCHUtlDlHqPTbRmvFrmTx(sf, hqP, tbCnt, TRUE);
4662 /* Check if last repetition */
4663 if (--hqP->tbInfo[tbCnt].fbkRepCntr)
4665 /* Update timingInfo for this hqP so that next subframe its picked up */
4666 RG_SCH_ADD_TO_CRNT_TIME(hqP->tbInfo[tbCnt].timingInfo, \
4667 hqP->tbInfo[tbCnt].timingInfo, 1);
4671 /* Take decision here based on the number
4672 * of DTX's,NACK's and ACK's received
4674 if (((hqP->tbInfo[tbCnt].ackCount) > (hqP->tbInfo[tbCnt].nackCount) +
4675 (hqP->tbInfo[tbCnt].dtxCount)))
4677 *isAck = TFU_HQFDB_ACK;
4679 /*even a single NACK indicates that UE received
4682 else if ( hqP->tbInfo[tbCnt].nackCount != 0 )
4684 *isAck = TFU_HQFDB_NACK;
4688 *isAck = TFU_HQFDB_DTX;
4692 hqP->tbInfo[tbCnt].isAckNackDtx = *isAck;
4695 #endif /* ifndef LTE_TDD */
4698 /* Freeing up the HARQ proc blocked for
4699 * indefinite time in case of Retx */
4701 * @brief This function handles the scenario in case Retx allocation is failed.
4705 * Function: rgSCHDhmDlRetxAllocFail
4708 * @param[in] RgSchUeCb *ue
4709 * @param[in] RgSchDlHqProcCb *hqP
4714 PUBLIC S16 rgSCHDhmDlRetxAllocFail
4717 RgSchDlHqProcCb *hqP
4720 PUBLIC S16 rgSCHDhmDlRetxAllocFail(ue, hqP)
4722 RgSchDlHqProcCb *hqP;
4726 RgInfRlsHqInfo *rlsHqInfo;
4728 Bool maxRetx = FALSE;
4729 RgSchCmnCell *cellSch;
4731 TRC2(rgSCHDhmDlRetxAllocFail);
4733 cell = hqP->hqE->cell;
4734 cellSch = RG_SCH_CMN_GET_CELL(cell);
4735 rlsHqInfo = &(cell->rlsHqArr[cell->crntHqIdx]);
4737 /* If retx was attempted for 1st TB, increment its retx alloc fail counter */
4738 if (hqP->tbInfo[0].state == HQ_TB_NACKED)
4740 hqP->tbInfo[0].cntrRetxAllocFail++;
4743 /* If retx was attempted for 2nd TB, increment its retx alloc fail counter */
4744 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
4746 hqP->tbInfo[1].cntrRetxAllocFail++;
4749 /* initialize MAC-SCH interface HARQ release info */
4750 rlsHqInfo->numUes = 0;
4751 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs = 0;
4753 /* Release HARQ proc for TB1 if Retx alloc failure count has reached max */
4754 if (hqP->tbInfo[0].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4756 if (hqP->hqE->msg4Proc == hqP)
4758 hqP->tbInfo[0].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4762 hqP->tbInfo[0].txCntr = hqP->hqE->maxHqTx;
4765 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[0].tbIdx, &maxRetx);
4770 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4771 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 0xFF; /* RGU_NACK_LOSS */;
4775 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4776 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4779 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4780 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4783 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4784 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 1;
4785 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4788 /* Release HARQ proc for TB2 if Retx alloc failure count has reached max */
4789 if (hqP->tbInfo[1].cntrRetxAllocFail == RG_SCH_MAX_RETX_ALLOC_FAIL)
4791 if (hqP->hqE->msg4Proc == hqP)
4793 hqP->tbInfo[1].txCntr = cell->dlHqCfg.maxMsg4HqTx;
4797 hqP->tbInfo[1].txCntr = hqP->hqE->maxHqTx;
4800 rgSCHDhmHqTbTrnsFail(cell, hqP, hqP->tbInfo[1].tbIdx, &maxRetx);
4802 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].status[\
4803 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = FALSE;
4804 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].tbId[\
4805 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs] = 2;
4806 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs++;
4809 /* MS_WORKAROUND for ccpu00122892 Temp fix for erroeneous RETX Harq release by rgSCHCmnDlAllocRetxRb */
4811 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
4812 (hqP->tbInfo[1].state != HQ_TB_NACKED))
4814 cellSch->apisDl->rgSCHDlProcRmvFrmRetx(cell, ue, hqP);
4817 /* send HARQ release to MAC */
4818 if (rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].numOfTBs > 0)
4820 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
4821 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].rnti = ue->ueId;
4822 rlsHqInfo->ueHqInfo[rlsHqInfo->numUes].hqProcId = hqP->procId;
4823 rlsHqInfo->numUes = 1;
4825 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
4826 RgSchMacRlsHq(&pst, rlsHqInfo);
4834 PRIVATE S16 rgSCHDhmUpdateAckNackHistory
4842 PRIVATE S16 rgSCHDhmUpdateAckNackHistory(cell, ueCb, hqfdbk, tbCnt)
4853 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4856 * If fdbk is ack update totalNoOfAck and ackNackHistory for
4859 if (hqfdbk == TFU_HQFDB_ACK)
4861 ueDl->laCb[tbCnt].deltaiTbs += DL_LA_STEPUP;
4865 ueDl->laCb[tbCnt].deltaiTbs = ueDl->laCb[tbCnt].deltaiTbs - DL_LA_STEPDOWN;
4868 printf("deltaiTbs[%d] cqibasediTbs[%d] iTbs[%d] tbCnt[%d]\n",
4869 ueDl->laCb[tbCnt].deltaiTbs, ueDl->laCb[tbCnt].cqiBasediTbs,
4870 (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100,
4873 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt);
4879 PUBLIC S16 rgSCHDhmUpdBlerBasediTbsEff
4886 PUBLIC S16 rgSCHDhmUpdBlerBasediTbsEff(cell, ueCb, tbCnt)
4896 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
4897 U8 cfi = cellSch->dl.currCfi;
4898 U8 maxiTbs = (*(RgSchCmnCqiToTbs *)(cellSch->dl.cqiToTbsTbl[0][cfi]))[RG_SCH_CMN_MAX_CQI - 1];
4899 maxiTbs = RG_SCH_DL_MAX_ITBS;
4901 ueDl = RG_SCH_CMN_GET_DL_UE(ueCb,cell);
4902 iTbs = (ueDl->laCb[tbCnt].deltaiTbs + ueDl->laCb[tbCnt].cqiBasediTbs)/100;
4906 ueDl->laCb[tbCnt].deltaiTbs = (maxiTbs * 100) - ueDl->laCb[tbCnt].cqiBasediTbs;
4907 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(maxiTbs, ueCb->cell->thresholds.maxDlItbs);
4911 ueDl->laCb[tbCnt].deltaiTbs = -(ueDl->laCb[tbCnt].cqiBasediTbs);
4912 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = 0;
4916 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0] = RGSCH_MIN(((ueDl->laCb[tbCnt].cqiBasediTbs +\
4917 ueDl->laCb[tbCnt].deltaiTbs)/100),
4918 ueCb->cell->thresholds.maxDlItbs);
4921 ueCb->ue5gtfCb.mcs = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4923 ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1] = ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0];
4925 /* Eff for CW for 1 Layer Tx */
4926 ueDl->mimoInfo.cwInfo[tbCnt].eff[0] =
4927 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[0][cfi]))\
4928 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[0]];
4930 /* Eff for CW for 2 Layer Tx */
4931 ueDl->mimoInfo.cwInfo[tbCnt].eff[1] =
4932 (*(RgSchCmnTbSzEff *)(cellSch->dl.cqiToEffTbl[1][cfi]))\
4933 [ueDl->mimoInfo.cwInfo[tbCnt].iTbs[1]];
4941 * @brief This function Processes the Hq Fdbk in case of
4942 * special Bundling in TDD (FAPIv1.1: Table 79)
4946 * Function: rgSCHDhmPrcSplBundlFdbk
4947 * Purpose: To Interpret the Harq Feedback according to
4948 * table 7.3-1: 36.213
4950 * 0 = 0 or None (UE detect at least one DL is missed)
4951 * 1 = 1 or 4 or 7 ACKs reported
4952 * 2 = 2 or 5 or 8 ACKs reported
4953 * 3 = 3 or 6 or 9 ACKs reported
4954 * 4 = DTX (UE did not transmit anything)
4956 * @param[in] TfuHqInfo *fdbk
4957 * @param[in] U8 hqCnt
4962 PRIVATE Void rgSCHDhmPrcSplBundlFdbk
4969 PRIVATE Void rgSCHDhmPrcSplBundlFdbk(cell, fdbk, hqCnt)
4979 TRC2(rgSCHDhmPrcSplBundlFdbk);
4981 /* Num of ACKs reported by UE */
4982 numOfAcks = fdbk->isAck[0];
4984 if(fdbk->isAck[0] == TFU_HQFDB_NACK ||
4985 fdbk->isAck[0] == TFU_HQFDB_DTX)
4991 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx,
4992 rgSchNumOfAcksToAckNack[(hqCnt-1)], (numOfAcks - 1));
4994 fdbk->isAck[0] = rgSchNumOfAcksToAckNack[(hqCnt-1)]
4997 /* The Hq Fdbk is a combined Ack/Nack for multiple Codewords within
4998 the PDSCH trasnmission (spatial bundling). So we have
4999 to assume same feedback for both codewords */
5001 for(U8 idx = 1 ; idx < TFU_MAX_HARQ_FDBKS; idx++)
5003 fdbk->isAck[idx] = fdbk->isAck[0];
5006 fdbk->isAck[1] = fdbk->isAck[0];
5014 * @brief This function adds HARQ process to FREE list
5018 * Function: rgSCHDhmHqPAdd2FreeLst
5021 * Invoked by: scheduler
5023 * @param[out] RgDlHqProc *hqP
5028 PUBLIC Void rgSCHDhmHqPAdd2FreeLst
5030 RgSchDlHqProcCb *hqP
5033 PUBLIC Void rgSCHDhmHqPAdd2FreeLst(hqP)
5034 RgSchDlHqProcCb *hqP;
5037 TRC2(rgSCHDhmHqPAdd2FreeLst)
5043 printf("Crashing already part of free lst\n");
5044 printf("Crashing %d \n", *p);
5048 cmLListAdd2Tail(&hqP->hqE->free, &hqP->lnk);
5049 hqP->hqPLst = &hqP->hqE->free;
5053 if (hqP->hqE->free.count > 8)
5056 printf("Crashing invalid hq count\n");
5057 printf("Crashing %d \n", *p);
5063 rgSCHLaaHndlHqProcFree(hqP);
5067 } /* rgSCHDhmHqPAdd2FreeLst */
5071 * @brief This function adds HARQ process to inUse list
5075 * Function: rgSCHDhmHqPAdd2InUseLst
5078 * Invoked by: scheduler
5080 * @param[out] RgDlHqProc *hqP
5085 PUBLIC Void rgSCHDhmHqPAdd2InUseLst
5087 RgSchDlHqProcCb *hqP
5090 PUBLIC Void rgSCHDhmHqPAdd2InUseLst(hqP)
5091 RgSchDlHqProcCb *hqP;
5094 TRC2(rgSCHDhmHqPAdd2InUseLst)
5100 printf("Crashing already part of inuse lst\n");
5101 printf("Crashing %d \n", *p);
5105 cmLListAdd2Tail(&hqP->hqE->inUse, &hqP->lnk);
5106 hqP->hqPLst = &hqP->hqE->inUse;
5110 if (hqP->hqE->inUse.count > 8)
5113 printf("Crashing invalid hq count \n");
5114 printf("Crashing %d \n", *p);
5120 } /* rgSCHDhmHqPAdd2InUseLst */
5123 * @brief This function adds HARQ process to FREE list
5127 * Function: rgSCHDhmHqPDelFrmFreeLst
5130 * Invoked by: scheduler
5132 * @param[out] RgDlHqProc *hqP
5137 PUBLIC Void rgSCHDhmHqPDelFrmFreeLst
5139 RgSchDlHqProcCb *hqP
5142 PUBLIC Void rgSCHDhmHqPDelFrmFreeLst(hqP)
5143 RgSchDlHqProcCb *hqP;
5146 TRC2(rgSCHDhmHqPDelFrmFreeLst)
5152 printf("Crashing not part of any lst\n");
5153 printf("Crashing %d \n", *p);
5158 if (hqP->hqPLst != &hqP->hqE->free)
5161 printf("Crashing del from wrong lst\n");
5162 printf("Crashing %d \n", *p);
5167 cmLListDelFrm(&hqP->hqE->free, &hqP->lnk);
5168 hqP->hqPLst = NULLP;
5171 if (hqP->hqE->free.count > 8)
5174 printf("Crashing invalid hq count\n");
5175 printf("Crashing %d \n", *p);
5181 } /* rgSCHDhmHqPDelFrmFreeLst */
5186 * @brief This function adds HARQ process to FREE list
5190 * Function: rgSCHDhmHqPDelFrmInUseLst
5193 * Invoked by: scheduler
5195 * @param[out] RgDlHqProc *hqP
5200 PUBLIC Void rgSCHDhmHqPDelFrmInUseLst
5202 RgSchDlHqProcCb *hqP
5205 PUBLIC Void rgSCHDhmHqPDelFrmInUseLst(hqP)
5206 RgSchDlHqProcCb *hqP;
5209 TRC2(rgSCHDhmHqPDelFrmInUseLst)
5215 printf("Crashing not part of any lst\n");
5216 printf("Crashing %d \n", *p);
5222 if (hqP->hqPLst != &hqP->hqE->inUse)
5225 printf("Crashing del from wrong lst\n");
5226 printf("Crashing %d \n", *p);
5231 cmLListDelFrm(&hqP->hqE->inUse, &hqP->lnk);
5232 hqP->hqPLst = NULLP;
5235 if (hqP->hqE->inUse.count > 8)
5238 printf("Crashing invalid hq count\n");
5239 printf("Crashing %d \n", *p);
5245 } /* rgSCHDhmHqPDelFrmInUseLst */
5248 /**********************************************************************
5251 **********************************************************************/