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 Scheduler common functions
29 **********************************************************************/
31 /** @file rg_sch_mga.c
32 @brief This module handles schedulers' measurement gap and ack-nack repetiton functionality */
34 static const char* RLOG_MODULE_NAME="MAC";
35 static int RLOG_MODULE_ID=4096;
36 static int RLOG_FILE_ID=169;
38 /* header include files -- defines (.h) */
39 #include "common_def.h"
44 #include "rg_sch_inf.h"
45 #include "rg_sch_err.h"
47 #include "rg_sch_cmn.h"
48 #include "rl_interface.h"
49 #include "rl_common.h"
51 /* header/extern include files (.x) */
52 #include "tfu.x" /* RGU types */
53 #include "lrg.x" /* layer management typedefs for MAC */
54 #include "rgr.x" /* layer management typedefs for MAC */
55 #include "rg_sch_inf.x" /* typedefs for Scheduler */
56 #include "rg_sch.x" /* typedefs for Scheduler */
59 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe ARGS((
62 RgrUeMeasGapCfg *cfg));
64 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe ARGS((
68 PRIVATE S16 rgSchAckNackRepUtlRmvUe ARGS((
72 PRIVATE Void rgSchAckNackRepUtlHdlTti ARGS((
74 CmLListCp *ackNackRepQ));
76 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti ARGS((
78 CmLListCp *measGapQ));
80 PRIVATE U8 rgSCHAckNakRepFindUlDuration ARGS((
83 CmLteTimingInfo repTime,
85 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl ARGS((
87 CmLteTimingInfo crntDlTime,
92 * @brief Handles Measurement gap and ack-nack repetition related
93 * configuration for a UE.
97 * Function : rgSCHMeasGapANRepUeCfg
99 * Invoking Module Processing:
100 * - This shall be invoked by SCH_GOM at UE configuration. It shall do the
101 * validations for the spec-defined values.
104 * - For UE-specific measurement gap related configuration,
105 * - If measurementGap is configured,
106 * - Update UE with the configured values.
107 * - Add Ue to cell->measGapCb->gapPrdQ depending on the gap period
108 * configuration at index = the configured gap offset.
109 * - measGapOffst = the configured gap offset
110 * - Initialize timers.
112 * - measGapOffst = RG_INVALID_MEASGAPQ_ID
113 * - For UE-specific ACK-NACK repetition related configuration,
114 * - Update the configured value. Set 'cfgRepCnt' variable value.
115 * - repCntr = cfgRepCnt.
116 * - qOffst = RG_INVALID_ACKNACKREPQ_ID
119 * @param[in] RgSchCellCb *cell
120 * @param[in] RgSchUeCb *ue
121 * @param[in] RgrUeCfg *ueCfg
128 PUBLIC S16 rgSCHMeasGapANRepUeCfg
135 PUBLIC S16 rgSCHMeasGapANRepUeCfg(cell, ue, ueCfg)
142 TRC2(rgSCHMeasGapANRepUeCfg);
145 ue->measGapCb.isMesGapEnabled = ueCfg->ueMesGapCfg.isMesGapEnabled;
147 if (ueCfg->ueMesGapCfg.isMesGapEnabled)
149 ue->measGapCb.gapPrd = ueCfg->ueMesGapCfg.gapPrd;
150 ue->measGapCb.gapOffst = ueCfg->ueMesGapCfg.gapOffst;
151 rgSCHMeasGapANRepUtlAddUe (cell, ue, &(ueCfg->ueMesGapCfg));
152 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
153 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
154 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
157 /* ACK NACK repetition part */
158 if (ueCfg->ueAckNackCfg.isAckNackEnabled)
160 ue->ackNakRepCb.cfgRepCnt = ueCfg->ueAckNackCfg.ackNackRepFactor;
161 ue->ackNakRepCb.repCntr = ue->ackNakRepCb.cfgRepCnt;
162 ue->ackNakRepCb.isAckNackEnabled = TRUE;
163 ue->ackNakRepCb.pucchRes = ueCfg->ueAckNackCfg.pucchAckNackRep;
164 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
165 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
166 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
172 * @brief Handles Measurement gap and ack-nack repetition related
173 * re-configuration for a UE.
177 * Function : rgSCHMeasGapANRepUeRecfg
179 * Invoking Module Processing:
180 * - This shall be invoked by SCH_GOM at UE re-configuration. It shall do the
181 * validations for the spec-defined values.
184 * - For measurement gap,
185 * - If measurement gap period or offset is re-configured, remove UE from
186 * the previous list, if any and add it to the new list.
187 * - Update configured values appropriately.
188 * - For ACK-NACK repetition,
189 * - Update the configured value. Set 'cfgRepCnt' variable value.
190 * - If (repCntr == 0)
191 * - repCntr = cfgRepCnt.
192 * - qOffst = RG_INVALID_ACKNACKREPQ_ID
194 * @param[in] RgSchCellCb *cell
195 * @param[in] RgSchUeCb *ue
196 * @param[in] RgrUeRecfg *ueRecfg
204 PUBLIC S16 rgSCHMeasGapANRepUeRecfg
211 PUBLIC S16 rgSCHMeasGapANRepUeRecfg(cell, ue, ueRecfg)
217 RgrUeMeasGapCfg *reCfg;
218 RgSchUeMeasGapCb *ueMeasCb;
219 RgrUeAckNackRepCfg *ackNackReCfg = &(ueRecfg->ueAckNackRecfg);
220 RgSchUeAckNakRepCb *ackNakRepCb = &(ue->ackNakRepCb);
222 TRC2(rgSCHMeasGapANRepUeRecfg);
225 reCfg = &(ueRecfg->ueMeasGapRecfg);
226 ueMeasCb = &(ue->measGapCb);
228 /* Removed extra comments
229 * Check this once again Check to see if anything changed or not */
230 if ((reCfg->isMesGapEnabled == TRUE) &&
231 (ueMeasCb->isMesGapEnabled == TRUE) &&
232 (reCfg->gapPrd == ueMeasCb->gapPrd) &&
233 (reCfg->gapOffst == ueMeasCb->gapOffst))
235 /* Nothing changed hence nothing to do */
239 if (reCfg->isMesGapEnabled)
241 if (ueMeasCb->isMesGapEnabled)
243 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
247 cmInitTimers (&ueMeasCb->measGapTmr, 1);
248 cmInitTimers (&ueMeasCb->measGapUlInactvTmr, 1);
249 cmInitTimers (&ueMeasCb->measGapDlInactvTmr, 1);
252 /* Add to the correct Measurement gap queue */
253 rgSCHMeasGapANRepUtlAddUe (cell, ue, reCfg);
255 ueMeasCb->gapPrd = reCfg->gapPrd;
256 ueMeasCb->gapOffst = reCfg->gapOffst;
257 ueMeasCb->isMesGapEnabled = TRUE;
258 } /* if new config has Measurement gap enabled */
261 if (ueMeasCb->isMesGapEnabled)
263 /* check if return value needed or not */
264 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
265 ueMeasCb->isMesGapEnabled = FALSE;
267 } /* if new config has Measurement gap disabled */
268 } /* For MeasGap configuration */
270 if (ackNackReCfg->isAckNackEnabled)
272 if (!ackNakRepCb->isAckNackEnabled)
274 ackNakRepCb->isAckNackEnabled = TRUE;
275 /* Timers need to be init immediately after config*/
276 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
277 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
278 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
279 } /* repetition was disabled */
280 ackNakRepCb->pucchRes = ackNackReCfg->pucchAckNackRep;
281 ackNakRepCb->cfgRepCnt = ackNackReCfg->ackNackRepFactor;
282 if (ackNakRepCb->repCntr == 0)
284 ackNakRepCb->repCntr = ackNackReCfg->ackNackRepFactor;
286 } /* repetition enabled in re configuration */
289 ackNakRepCb->isAckNackEnabled = FALSE;
290 } /* repetition disabled in re configuration */
295 /** @brief This function is a utility to add the UE to the correct Measurement
296 * queue present in the cellCb.
311 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe
318 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe (cell, ue, cfg)
321 RgrUeMeasGapCfg *cfg;
325 TRC2(rgSCHMeasGapANRepUtlAddUe);
329 case RG_MEAS_GAPPRD_40:
330 /* Insert the UE into the linked list based on the gap Offset */
331 ue->measGapCb.measQLnk.node = (PTR)ue;
332 cmLListAdd2Tail (&(cell->measGapCb.gapPrd40Q[cfg->gapOffst]),
333 &(ue->measGapCb.measQLnk));
335 case RG_MEAS_GAPPRD_80:
336 ue->measGapCb.measQLnk.node = (PTR)ue;
337 cmLListAdd2Tail (&(cell->measGapCb.gapPrd80Q[cfg->gapOffst]),
338 &(ue->measGapCb.measQLnk));
341 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
342 "rgSCHMeasGapANRepUeRecfg() Incorrect GAP Period"
343 "CRNTI:%d",ue->ueId);
347 } /* end of rgSCHMeasGapANRepUtlAddUe */
350 /** @brief This function is a utility function to remove the ue from the measQ
351 * preset in tthe cell Cb.
365 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe
371 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe (cell, ue)
377 TRC2(rgSCHMeasGapANRepUtlRmvUe);
379 switch (ue->measGapCb.gapPrd)
381 case RG_MEAS_GAPPRD_40:
382 /* Remove from the existing list */
383 cmLListDelFrm (&(cell->measGapCb.gapPrd40Q[ue->measGapCb.gapOffst]),
384 &(ue->measGapCb.measQLnk));
385 ue->measGapCb.measQLnk.node = NULLP;
387 case RG_MEAS_GAPPRD_80:
388 /* Remove from the existing list */
389 cmLListDelFrm (&(cell->measGapCb.gapPrd80Q[ue->measGapCb.gapOffst]),
390 &(ue->measGapCb.measQLnk));
391 ue->measGapCb.measQLnk.node = NULLP;
395 } /* end of rgSCHMeasGapANRepUtlRmvUe */
398 * @brief Frees Measurement gap and ack-nack repetition related data structures in UE
402 * Function : rgSCHMeasGapANRepUeDel
404 * Invoking Module Processing:
405 * - This shall be invoked by SCH_GOM at Ue deletion.
408 * - For measurement gap,
409 * - if (measGapOffst != RG_INVALID_MEASGAPQ_ID)
410 * - Remove from the measurement queue depending on the measGapPrd
412 * - Delete all timers
413 * - For ACK-NACK repetition,
414 * - if (qOffst != RG_INVALID_ACKNACKREPQ_ID)
415 * - Remove from the ackNakRepQ queue
416 * - Delete all timers
419 * @param[in] RgSchCellCb *cell
420 * @param[in] RgSchUeCb *ue
427 PUBLIC Void rgSCHMeasGapANRepUeDel
434 PUBLIC Void rgSCHMeasGapANRepUeDel(cell, ue, isUeDel)
442 TRC2(rgSCHMeasGapANRepUeDel);
444 if (ue->measGapCb.isMesGapEnabled)
446 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
447 /* Must stop the timer if its running */
448 if (ue->measGapCb.isMeasuring)
450 rgSCHTmrStopTmr (cell, RG_SCH_TMR_MEASGAP, ue);
453 ue->measGapCb.isMesGapEnabled = FALSE;
456 /* Stop timers if running */
457 if (ue->dl.dlInactvMask)
459 if (ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE)
461 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_MEASGAP, ue);
463 if (ue->dl.dlInactvMask & RG_ACKNAKREP_INACTIVE)
465 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_ACKNACK, ue);
467 ue->dl.dlInactvLnk.node = NULLP;
469 if (ue->ul.ulInactvMask)
471 if (ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE)
473 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_MEASGAP, ue);
475 if (ue->ul.ulInactvMask & RG_ACKNAKREP_INACTIVE)
477 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_ACKNACK, ue);
479 ue->ul.ulInactvLnk.node = NULLP;
482 /* ccpu00133470- Releasing ACKNACK Rep UE Deleted */
483 if (isUeDel & ue->ackNakRepCb.isAckNakRep)
485 rgSCHTmrStopTmr (cell, RG_SCH_TMR_ACKNACK_REP, ue);
486 rgSchAckNackRepUtlRmvUe (cell, ue);
491 /** @brief This function deletes the UEs information related to ACK NACK
499 * - Mainly we need to remove the UEs hqProcs from the ackNackQ(s)
500 * present in the subframes.
508 PRIVATE S16 rgSchAckNackRepUtlRmvUe
514 PRIVATE S16 rgSchAckNackRepUtlRmvUe (cell, ue)
523 RgSchDlHqProcCb *hqP;
526 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
528 TRC3(rgSchAckNackRepUtlRmvUe);
530 for (hqIdx = 0; hqIdx < hqEnt->numHqPrcs; hqIdx++)
532 hqP = &hqEnt->procs[hqIdx];
533 /* Starting from index 1 as index 0 isn't used */
534 for (repIdx = 1; repIdx < ue->ackNakRepCb.cfgRepCnt; repIdx++)
536 for (tbCnt = 0; tbCnt < 2; tbCnt++)
538 if ((hqP->tbInfo[tbCnt].crntSubfrm[repIdx] != NULLP) &&
539 (hqP->tbInfo[tbCnt].anRepLnk[repIdx].node != NULLP))
541 cmLListDelFrm(&((hqP->tbInfo[tbCnt].crntSubfrm[repIdx])->\
542 ackNakRepQ), &hqP->tbInfo[tbCnt].anRepLnk[repIdx]);
543 hqP->tbInfo[tbCnt].anRepLnk[repIdx].node = NULLP;
544 hqP->tbInfo[tbCnt].crntSubfrm[repIdx] = NULLP;
555 * @brief Per TTI processing for measurement gap and ack nack repetition
560 * Function : rgSCHMeasGapANRepTtiHndl
562 * Invoking Module Processing:
563 * - This shall be invoked by SCH_TOM on recieving TTI indication from PHY
564 * . SCH_TOM shall update the cell->crntTime before invoking this API.
567 * - Compute qOffset for 40ms queue as =
568 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_40.
569 * - Mark all the UEs at computed offset for performing measurement. Set
570 * isMeasuring = TRUE.
571 * - Start measGapTmr for each UE:
572 * - length = RG_MEAS_GAP_LEN.
573 * - event = RG_MEASGAP_ON
574 * - handler = rgSCHMeasGapANRepTmrExpry
575 * - Reinitalize the list at the offset.
576 * - Compute qOffset for 80ms queue as =
577 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_80.
578 * - Mark all the UEs at computed offset for performing measurement. Set
579 * isMeasuring = TRUE.
580 * - Start measGapTmr for each UE:
581 * - length = RG_MEAS_GAP_LEN.
582 * - event = RG_MEASGAP_ON
583 * - handler = rgSCHMeasGapANRepTmrExpry
584 * - Reinitalize the list at the offset.
585 * - Compute qOffset for ACK NACK repetition queue as =
586 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MAX_NUM_DLSF.
587 * - Mark all the UEs at computed offset for performing ack-nack repetition. Set
588 * isAckNakRep = TRUE.
589 * - Start ackNakRepTmr for each UE:
590 * - length = repCntr.
591 * - event = RG_ACKNAKREP_ON
592 * - handler = rgSchAckNakRepTmrExpry
593 * - Reinitalize the list at the offset.
594 * - 'isMeasuring' bool value shall be cheked
595 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
596 * and if 'TRUE', no dataRecpReq shall be sent.
597 * - While sending NACK as feedback to UE and if 'TRUE' no PHICH shall
598 * be sent and shall mark the UE for adaptive re-tx.
599 * - While sending HqFbkRecpReq for a UE (applicable only if ACK NACK
600 * repetition coincides) and if 'TRUE',
601 * - The request shall not be sent.
602 * - Decrement repCntr
603 * - if (repCntr == 0)
604 * - Delete UE from the list.
605 * - Move the Ue to next subframe's list of ACK-NACK repeating UEs.
606 * - 'isAckNakRep' bool value shall be cheked
607 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
608 * and if 'TRUE', no dataRecpReq shall be sent.
609 * - Check if any refresh for these cell-specific queues is needed
610 * anywhere else as well.
611 * - Check if TTI miss needs some trigger to the module.
614 * @param[in] RgSchCellCb *cell
621 PUBLIC S16 rgSCHMeasGapANRepTtiHndl
626 PUBLIC S16 rgSCHMeasGapANRepTtiHndl(cell)
633 CmLteTimingInfo repTime;
635 TRC2(rgSCHMeasGapANRepTtiHndl);
637 /* Measurement GAP Starts at offSet - however at MAC we are concerned at
638 * subframe + TFU_DELTA.
641 /* Introduced timing delta for DL control in FDD */
643 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) %
646 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) %
649 queue = &(cell->measGapCb.gapPrd40Q[offset]);
650 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
652 /* Introduced timing delta for DL control in FDD */
654 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) %
657 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) %
660 queue = &(cell->measGapCb.gapPrd80Q[offset]);
661 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
663 /* for ACK NACK repetition starts at offset - however at MAC we are
664 * concerned with subframe - TFU_DELTA */
665 /* offset = ((cell->crntTime.sfn * 10) + cell->crntTime.slot) %
666 * RG_MAX_NUM_DLSF; */
667 /* We wish to get the subframe whose HARQ Reception request would go out in
668 * this subframe. HARQ_RTT - TFU_DELTA
670 /* Introduced timing delta for reception req */
673 //RGSCHSUBFRMCRNTTIME(cell->crntTime, repTime, (4 - TFU_DELTA));
674 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
676 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
678 dlSf = rgSCHUtlSubFrmGet (cell, repTime);
679 queue = &(dlSf->ueLst);
680 rgSchAckNackRepUtlHdlTti (cell, queue);
685 /** @brief This function Marks the UE as ackNakRep so that Reception request
686 * isnt sent for any other thing than HARQ.
693 * - Loop through HARQ procs of the DlSf.
694 * - If the UE is a repeating one
695 * - Mark as ackNakRep = TRUE
698 * @param RgSchCellCb *cell
699 * @param CmLListCp *ackNakRepQ
703 PRIVATE Void rgSchAckNackRepUtlHdlTti
706 CmLListCp *ackNackRepQ
709 PRIVATE Void rgSchAckNackRepUtlHdlTti (cell, ackNackRepQ)
711 CmLListCp *ackNackRepQ;
717 TRC2(rgSchAckNackRepUtlHdlTti);
719 node = ackNackRepQ->first;
722 ue = (RgSchUeCb *)(node->node);
723 if ((NULLP != ue) && (ue->ackNakRepCb.isAckNackEnabled))
725 ue->ackNakRepCb.isAckNakRep = TRUE;
726 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_ACKNACK_REP,
727 ue->ackNakRepCb.repCntr);
735 /** @brief This function
750 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti
756 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti (cell, measGapQ)
764 TRC2(rgSCHMeasGapANRepUtlHdlTti);
766 node = measGapQ->first;
769 ue = (RgSchUeCb*)node->node;
770 ue->measGapCb.isMeasuring = TRUE;
771 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_MEASGAP, RG_SCH_MEAS_GAP_LEN);
779 * @brief Determines the list of UEs inactive for DL scheduling due to
780 * measurement gap and ack nack repetitions
784 * Function : rgSCHMeasGapANRepGetDlInactvUe
786 * Invoking Module Processing:
787 * - This API shall be invoked to get list of inactive UEs for downlink
788 * scheduling due to measurement gaps and ACK NACK repetitions.
791 * - Compute qOffset for 40ms or 80ms queue as =
792 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
793 * RG_SCH_CMN_HARQ_INTERVAL)
794 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
795 * - Add all the UEs at computed offset to dlInactvUeLst since the
796 * DL transmission or feedback transmission from UE for DL
797 * transmissions shall collide with measurement gap.
798 * - Mark each UE. Set dlInactvMask |= RG_MEASGAP_INACTIVE
799 * - Start measGapDlInactvTmr timer for each UE,
800 * - length = RG_MEAS_GAP_LEN + RG_SCH_CMN_HARQ_INTERVAL
801 * - event = RG_MEASGAP_DLINACTV
802 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
803 * - Compute qOffset for ACK NACK repetition queue as =
804 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
805 * RG_SCH_CMN_HARQ_INTERVAL -1)
807 * - Add all the UEs at computed offset to dlInactvUeLst since the
808 * feedback transmission from UE for DL transmissions shall
809 * collide with ACK NACK repetition of the UE.
810 * - Mark each UE. Set dlInactvMask |= RG_ACKNAKREP_INACTIVE
811 * - Start ackNakRepDlInactvTmr timer for each UE,
812 * - length = repCntr - 1
813 * - event = RG_ACKNAKREP_DLINACTV
814 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
815 * - Verify the above computations before coding
819 * @param[in] RgSchCellCb *cell
820 * @param[out] CmLListCp *dlInactvUeLst
825 PUBLIC S16 rgSCHMeasGapANRepGetDlInactvUe
828 CmLListCp *dlInactvUeLst
831 PUBLIC S16 rgSCHMeasGapANRepGetDlInactvUe(cell, dlInactvUeLst)
833 CmLListCp *dlInactvUeLst;
842 CmLteTimingInfo ackNakTime;
848 RgSchDlHqProcCb *hqP;
852 TRC2(rgSCHMeasGapANRepGetDlInactvUe);
854 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + RG_DL_DELTA;
857 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
858 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
859 RG_SCH_TDD_DL_SUBFRAME)
864 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
865 if(dlSf->dlFdbkInfo.sfnOffset > 0)
868 (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES+ \
869 RGSCH_NUM_SUB_FRAMES - ackNakTime.subframe + \
870 dlSf->dlFdbkInfo.subframe;
874 harqFdbkOffset = dlSf->dlFdbkInfo.subframe - ackNakTime.subframe;
877 harqFdbkOffset = RG_SCH_CMN_HARQ_INTERVAL;
879 /* Calc offset for Measurement gap 40 */
880 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_40;
881 queue = &(cell->measGapCb.gapPrd40Q[offset]);
886 ue = (RgSchUeCb*)node->node;
887 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
888 /* Add to the inactv list */
889 ue->dl.dlInactvLnk.node = (PTR)ue;
890 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
892 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
893 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
897 /* Calc offset for Measurement gap 80 */
898 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_80;
899 queue = &(cell->measGapCb.gapPrd80Q[offset]);
904 ue = (RgSchUeCb*)node->node;
905 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
906 /* Add to the inactv list */
907 ue->dl.dlInactvLnk.node = (PTR)ue;
908 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
910 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
911 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
915 /* Calc offset for ACK NACK repetition */
916 /*offset = (cell->crntTime.sfn * 10 +
917 cell->crntTime.slot + RG_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL - 1)
919 /* The ackNakRepQ resides in each dlSf corresponding to the repStart */
920 /* Must pick up the subframe that was scheduled in the last TTI */
922 if(cell->ulDlCfgIdx == 5)
926 rgSCHUtlGetPrevDlSfInfo(cell, ackNakTime, &ackNakTime, &repCntr);
927 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
928 /* crnt DL subframe */
929 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
933 /* Go to the subframe being scheduled */
934 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
935 /* Go to the previous subframe */
936 RGSCHDECRFRMCRNTTIME(ackNakTime, ackNakTime, 1);
940 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime,
943 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
945 queue = &(dlSf->ueLst);
950 ue = (RgSchUeCb *)(node->node);
952 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
955 hqP = (RgSchDlHqProcCb *)hqNode->node;
956 hqNode = hqNode->next;
957 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
959 tbCb = &hqP->tbInfo[i];
960 if (tbCb->fbkRepCntr > 0)
962 ue->dl.dlInactvMask |= RG_ACKNAKREP_INACTIVE;
963 /* Check if already added to the list */
964 if (!(ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE))
966 /* Add to the inactv list */
967 ue->dl.dlInactvLnk.node = (PTR)ue;
968 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
972 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
973 (U8)(ue->ackNakRepCb.repCntr - 1));
974 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK, repCntr);
976 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK,
977 (ue->ackNakRepCb.repCntr - 1));
987 * @brief Determines the list of UEs inactive for UL scheduling due to
988 * measurement gap and ack nack repetitions
992 * Function : rgSCHMeasGapANRepGetUlInactvUe
994 * Invoking Module Processing:
995 * - This API shall be invoked to get list of inactive UEs for uplink
996 * scheduling due to measurement gaps and ACK NACK repetitions.
999 * - Compute qOffset for 40ms or 80ms queue as =
1000 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
1001 * RG_SCH_CMN_HARQ_INTERVAL)
1002 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
1003 * - Add all the UEs at computed offset to ulInactvUeLst since the UL
1004 * transmissions shall collide with measurement gap.
1005 * - Mark each UE. Set ulInactvMask |= RG_MEASGAP_INACTIVE
1006 * - Start measGapUlInactvTmr timer for each UE
1007 * - length = RG_MEAS_GAP_LEN
1008 * - event = RG_MEASGAP_ULINACTV
1009 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
1010 * - Compute qOffset for ACK NACK repetition queue as =
1011 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
1012 * RG_SCH_CMN_HARQ_INTERVAL)
1013 * % RG_MAX_NUM_DLSF.
1014 * - Add all the UEs at computed offset to ulInactvUeLst since the
1015 * feedback transmission from UE for DL transmissions shall
1016 * collide with repeating ACK ACK-NACKs.
1017 * - Mark each UE. Set ulInactvMask |= RG_ACKNAKREP_INACTIVE
1018 * - Start ackNakRepUlInactv timer for each UE
1019 * - length = repCntr
1020 * - event = RG_ACKNAKREP_ULINACTV
1021 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
1022 * - Verify the above computations before coding
1025 * @param[in] RgSchCellCb *cell
1026 * @param[out] CmLListCp *ulInactvUeLst
1032 PUBLIC S16 rgSCHMeasGapANRepGetUlInactvUe
1035 CmLListCp *ulInactvUeLst
1038 PUBLIC S16 rgSCHMeasGapANRepGetUlInactvUe(cell, ulInactvUeLst)
1040 CmLListCp *ulInactvUeLst;
1049 CmLteTimingInfo ackNakTime;
1057 RgSchDlHqProcCb *hqP;
1058 RgSchDlHqTbCb *tbCb;
1061 TRC2(rgSCHMeasGapANRepGetUlInactvUe);
1063 /*ccpu00139481- Meas Gap should be monitored in UL with TFU_ULCNTRL_DLDELTA*/
1064 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + \
1065 TFU_ULCNTRL_DLDELTA;
1067 pdcchToPuschGap = RGSCH_PDCCH_PUSCH_DELTA;
1069 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_ULCNTRL_DLDELTA);
1070 pdcchToPuschGap = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][ackNakTime.subframe];
1071 for(idx=0; pdcchToPuschGap && (idx< (pdcchToPuschGap+RG_SCH_MEAS_GAP_LEN)) ; idx++)
1074 /* Calc offset for Measurement gap 40 */
1075 offset = (schedTime + pdcchToPuschGap -idx + RG_MEAS_GAPPRD_40) % RG_MEAS_GAPPRD_40;
1076 queue = &(cell->measGapCb.gapPrd40Q[offset]);
1077 node = queue->first;
1080 ue = (RgSchUeCb*)node->node;
1081 if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1083 ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
1084 /* Add to the inactv list */
1085 ue->ul.ulInactvLnk.node = (PTR)ue;
1086 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1087 /* Start timer Note the timer is started for a value GAP_LEN +
1088 * RG_SCH_CMN_HARQ_INTERVAL. The "4"
1089 * is added because for UE to transmit, the PDCCH must be sent 4 subframes
1090 * ahead - UE cant read PDCCH format0 if it is in measurement gap. */
1091 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1092 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1093 //printf("Starting Meas Gap 40 @ DL TTI- (%d:%d) K-%d offset-%d Len %d \n", ackNakTime.sfn, ackNakTime.subframe, harqFdbkOffset, offset, RG_SCH_MEAS_GAP_LEN + harqFdbkOffset-idx);
1098 /* Calc offset for Measurement gap 80 */
1099 offset = (schedTime + pdcchToPuschGap - idx + RG_MEAS_GAPPRD_80) % RG_MEAS_GAPPRD_80;
1100 queue = &(cell->measGapCb.gapPrd80Q[offset]);
1102 node = queue->first;
1105 ue = (RgSchUeCb*)node->node;
1106 if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1108 ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
1109 /* Add to the inactv list */
1110 ue->ul.ulInactvLnk.node = (PTR)ue;
1111 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1113 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1114 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1115 //printf("Starting Meas Gap 80 @ DL TTI- (%d:%d) K-%d offset-%d Len %d \n", ackNakTime.sfn, ackNakTime.subframe, harqFdbkOffset, offset, RG_SCH_MEAS_GAP_LEN + harqFdbkOffset-idx);
1120 /* Calc offset for ACK NACK repetition */
1121 /*offset = (cell->crntTime.sfn * 10 +
1122 cell->crntTime.slot + RG_UL_SCHED_DELTA +
1123 RG_SCH_CMN_HARQ_INTERVAL ) % RG_MAX_NUM_DLSF;*/
1125 /* Must get the DLSF that is scheduled at TFU_DELTA Away */
1127 if(cell->ulDlCfgIdx == 5)
1131 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DELTA);
1132 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
1133 RG_SCH_TDD_DL_SUBFRAME)
1138 /* Introduced timing delta for DL control in FDD */
1139 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DLCNTRL_DLDELTA);
1141 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
1142 queue = &(dlSf->ueLst);
1144 node = queue->first;
1147 ue = (RgSchUeCb *)(node->node);
1149 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
1152 hqP = (RgSchDlHqProcCb *)hqNode->node;
1153 hqNode = hqNode->next;
1154 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1156 tbCb = &hqP->tbInfo[i];
1157 if (tbCb->fbkRepCntr > 0)
1159 ue->ul.ulInactvMask |= RG_ACKNAKREP_INACTIVE;
1160 /* Check if already added to the list */
1161 if (!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1163 /* Add to the inactv list */
1164 ue->ul.ulInactvLnk.node = (PTR)ue;
1165 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1169 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
1170 ue->ackNakRepCb.repCntr);
1171 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK, repCntr);
1173 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK,
1174 (ue->ackNakRepCb.repCntr));
1184 * @brief Handles processing of DL Inactive timer expiry at the end of
1185 * measurement gap or ack nack repetition for a UE
1189 * Function : rgSCHMeasGapANRepDlInactvTmrExpry
1191 * Invoking Module Processing:
1192 * - This API shall be invoked to process DL inactive timer expiry
1195 * - If timer event is RG_MEASGAP_DLINACTV,
1196 * - dlInactvMask &= ~RG_MEASGAP_INACTIVE
1197 * - If timer event is RG_ACKNAKREP_DLINACTV,
1198 * - dlInactvMask &= ~RG_ACKNAKREP_INACTIVE
1199 * - if (!dlInactvMask)
1200 * - Invoke DL scheduler to put the UE back into the scheduling queues.
1201 * - Re-initialize timer.
1204 * @param[in] RgSchUeCb *ue
1205 * @param[in] Check if some timer related parameter needs to be passed
1211 PUBLIC Void rgSCHMeasGapANRepDlInactvTmrExpry
1217 PUBLIC Void rgSCHMeasGapANRepDlInactvTmrExpry(ue, tmrEvnt)
1223 RgSchCellCb *cell = ue->cell;
1224 TRC2(rgSCHMeasGapANRepDlInactvTmrExpry);
1228 case RG_SCH_TMR_DL_MEASGAP:
1229 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1231 case RG_SCH_TMR_DL_ACKNACK:
1232 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1235 if (!ue->dl.dlInactvMask)
1237 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
1238 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
1244 * @brief Handles processing of UL Inactive timer expiry at the end of
1245 * measurement gap or ack nack repetition for a UE
1249 * Function : rgSCHMeasGapANRepUlInactvTmrExpry
1251 * Invoking Module Processing:
1252 * - This API shall be invoked to process UL inactive timer expiry
1255 * - If timer event is RG_MEASGAP_ULINACTV,
1256 * - ulInactvMask &= ~RG_MEASGAP_INACTIVE
1257 * - If timer event is RG_ACKNAKREP_ULINACTV,
1258 * - ulInactvMask &= ~RG_ACKNAKREP_INACTIVE
1259 * - if (!ulInactvMask)
1260 * - Invoke UL scheduler to put the UE back into the scheduling queues.
1261 * - Re-initialize timer.
1264 * @param[in] RgSchUeCb *ue
1265 * @param[in] Check if some timer related parameter needs to be passed
1271 PUBLIC Void rgSCHMeasGapANRepUlInactvTmrExpry
1277 PUBLIC Void rgSCHMeasGapANRepUlInactvTmrExpry(ue, tmrEvnt)
1282 RgSchCellCb *cell = ue->cell;
1283 TRC2(rgSCHMeasGapANRepUlInactvTmrExpry);
1287 case RG_SCH_TMR_UL_MEASGAP:
1288 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1290 case RG_SCH_TMR_UL_ACKNACK:
1291 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1294 if (!ue->ul.ulInactvMask)
1296 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
1297 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
1303 * @brief Handles processing of measurement gap timer expiry at the end of
1308 * Function : rgSCHMeasGapANRepTmrExpry
1310 * Invoking Module Processing:
1311 * - This API shall be invoked to process measurement gap timer expiry
1314 * - Set ue->isMeasuring = FALSE
1315 * - Re-initialize timer.
1318 * @param[in] RgSchUeCb *ue
1319 * @param[in] Check if some timer related parameter needs to be passed
1325 PUBLIC Void rgSCHMeasGapANRepTmrExpry
1330 PUBLIC Void rgSCHMeasGapANRepTmrExpry(ue)
1335 TRC2(rgSCHMeasGapANRepTmrExpry);
1337 ue->measGapCb.isMeasuring = FALSE;
1338 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
1344 * @brief Handles processing of ACK-NACK repetition timer expiry at the end of
1345 * ACK-NACK repetition.
1349 * Function : rgSchAckNakRepTmrExpry
1351 * Invoking Module Processing:
1352 * - This API shall be invoked to process ACK-NACK repetition timer expiry
1355 * - Set ue->isAckNakRep = FALSE
1356 * - Re-initialize timer.
1359 * @param[in] RgSchUeCb *ue
1360 * @param[in] Check if some timer related parameter needs to be passed
1366 PUBLIC Void rgSCHAckNakRepTmrExpry
1371 PUBLIC Void rgSCHAckNakRepTmrExpry(ue)
1376 TRC2(rgSCHAckNakRepTmrExpry);
1378 ue->ackNakRepCb.isAckNakRep = FALSE;
1379 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
1386 * @brief Adds ACK-NACK repeating UEs to the ackNakRepQ
1390 * Function : rgSchAckNakRepAddToQ
1392 * Invoking Module Processing:
1393 * - This API shall be invoked for adding list of UEs to the ACK-NACK
1394 * repeating queue at appropriate poistion. Invoking module shall invoke
1395 * with the list of ACK-NACK repeating UEs for a sub-frame and timing info
1396 * at which ACK NACK repetition shall start for the UEs.
1399 * - Determine the qOffset depending on the timing info as
1400 * - qOffset = (repStartTime->sfn *10 + repStartTime->subframe) % RG_MAX_NUM_DLSF
1401 * - Initialize the list at the qOffset.
1402 * - For each UE in the list,
1403 * - Add the UE to ackNakRepQ to the list at the determined qOffset.
1404 * - Set ue->qOffset = qOffset
1405 * - Initialize timers.
1408 * @param[in] RgSchCellCb *cell
1409 * @param[in] RgSchDlSf *crntDlSf
1410 * @param[in] CmLteTimingInfo repStartTime
1417 PUBLIC Void rgSCHAckNakRepAddToQ
1423 PUBLIC Void rgSCHAckNakRepAddToQ(cell, crntDlSf)
1425 RgSchDlSf *crntDlSf;
1431 RgSchDlHqProcCb *hqP;
1432 RgSchDlHqTbCb *tbCb;
1435 TRC2(rgSCHAckNakRepAddToQ);
1437 node = crntDlSf->ueLst.first;
1440 ue = (RgSchUeCb *)(node->node);
1442 hqNode = ue->dl.dlSfHqInfo[cell->cellId][crntDlSf->dlIdx].hqPLst.first;
1445 hqP = (RgSchDlHqProcCb *)hqNode->node;
1446 hqNode = hqNode->next;
1447 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1449 tbCb = &hqP->tbInfo[i];
1450 /* Add UEs that have enabled ACK NACK repetition */
1451 if (ue->ackNakRepCb.isAckNackEnabled)
1453 tbCb->fbkRepCntr = ue->ackNakRepCb.cfgRepCnt;
1454 tbCb->fbkRecpRepCntr = ue->ackNakRepCb.cfgRepCnt;
1455 /* Removed init of timers as the init will be happening during
1456 * config or timer expiry*/
1467 * @brief Finds the number of subframes used for ACK-NACK cycle
1471 * Function : rgSCHAckNakRepFindUlDuration
1473 * This function finds the number of subframes required
1474 * for ACK-NACK repetition cycle based on UL subframes.
1476 * @param[in] RgSchCellCb *cell
1477 * @param[in] RgSchDlSf *dlSf
1478 * @param[in] CmLteTimingInfo repTime
1479 * @param[in] U8 repCnt
1486 PRIVATE U8 rgSCHAckNakRepFindUlDuration
1490 CmLteTimingInfo repTime,
1494 PRIVATE U8 rgSCHAckNakRepFindUlDuration(cell, dlSf, repTime, repCnt)
1497 CmLteTimingInfo repTime;
1501 CmLteTimingInfo ulfrm;
1503 U16 ulDlCfgIdx = cell->ulDlCfgIdx;
1508 TRC2(rgSCHAckNakRepFindUlDuration)
1509 rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, repTime, &noSubfrms);
1510 RG_SCH_ADD_TO_CRNT_TIME(repTime, ulfrm, noSubfrms);
1512 idx = ulfrm.subframe;
1515 idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
1516 if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] ==
1517 RG_SCH_TDD_UL_SUBFRAME)
1529 * @brief Finds the number of subframes used for ACK-NACK cycle
1533 * Function : rgSCHAckNakRepGetUlOffsetFrmDl
1535 * This function finds the number of subframes after
1536 * which UL subframes are present for the gicen DL
1539 * @param[in] RgSchDlSf *dlSf
1540 * @param[in] CmLteTimingInfo crntDlTime
1541 * @param[in] U8 *noSubfrms
1548 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl
1551 CmLteTimingInfo crntDlTime,
1555 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, crntDlTime, noSubfrms)
1557 CmLteTimingInfo crntDlTime;
1561 TRC2(rgSCHAckNakRepGetUlOffsetFrmDl)
1563 if(dlSf->dlFdbkInfo.sfnOffset != 0)
1565 *noSubfrms = (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES;
1566 *noSubfrms = *noSubfrms + RGSCH_NUM_SUB_FRAMES - crntDlTime.subframe;
1567 *noSubfrms = *noSubfrms + dlSf->dlFdbkInfo.subframe;
1571 *noSubfrms = dlSf->dlFdbkInfo.subframe - crntDlTime.subframe;
1577 /**********************************************************************
1580 **********************************************************************/