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 "envopt.h" /* environment options */
40 #include "envdep.h" /* environment dependent */
41 #include "envind.h" /* environment independent */
42 #include "gen.h" /* general layer */
43 #include "ssi.h" /* system service interface */
44 #include "cm_hash.h" /* common hash list */
45 #include "cm_llist.h" /* common linked list library */
46 #include "cm_err.h" /* common error */
47 #include "cm_lte.h" /* common LTE */
52 #include "rg_sch_inf.h"
53 #include "rg_sch_err.h"
55 #include "rg_sch_cmn.h"
56 #include "rl_interface.h"
57 #include "rl_common.h"
59 /* header/extern include files (.x) */
60 #include "gen.x" /* general layer typedefs */
61 #include "ssi.x" /* system services typedefs */
62 #include "cm5.x" /* common timers */
63 #include "cm_hash.x" /* common hash list */
64 #include "cm_lib.x" /* common library */
65 #include "cm_llist.x" /* common linked list */
66 #include "cm_mblk.x" /* memory management */
67 #include "cm_tkns.x" /* common tokens */
68 #include "cm_lte.x" /* common tokens */
69 #include "tfu.x" /* RGU types */
70 #include "lrg.x" /* layer management typedefs for MAC */
71 #include "rgr.x" /* layer management typedefs for MAC */
72 #include "rg_sch_inf.x" /* typedefs for Scheduler */
73 #include "rg_sch.x" /* typedefs for Scheduler */
76 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe ARGS((
79 RgrUeMeasGapCfg *cfg));
81 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe ARGS((
85 PRIVATE S16 rgSchAckNackRepUtlRmvUe ARGS((
89 PRIVATE Void rgSchAckNackRepUtlHdlTti ARGS((
91 CmLListCp *ackNackRepQ));
93 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti ARGS((
95 CmLListCp *measGapQ));
97 PRIVATE U8 rgSCHAckNakRepFindUlDuration ARGS((
100 CmLteTimingInfo repTime,
102 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl ARGS((
104 CmLteTimingInfo crntDlTime,
109 * @brief Handles Measurement gap and ack-nack repetition related
110 * configuration for a UE.
114 * Function : rgSCHMeasGapANRepUeCfg
116 * Invoking Module Processing:
117 * - This shall be invoked by SCH_GOM at UE configuration. It shall do the
118 * validations for the spec-defined values.
121 * - For UE-specific measurement gap related configuration,
122 * - If measurementGap is configured,
123 * - Update UE with the configured values.
124 * - Add Ue to cell->measGapCb->gapPrdQ depending on the gap period
125 * configuration at index = the configured gap offset.
126 * - measGapOffst = the configured gap offset
127 * - Initialize timers.
129 * - measGapOffst = RG_INVALID_MEASGAPQ_ID
130 * - For UE-specific ACK-NACK repetition related configuration,
131 * - Update the configured value. Set 'cfgRepCnt' variable value.
132 * - repCntr = cfgRepCnt.
133 * - qOffst = RG_INVALID_ACKNACKREPQ_ID
136 * @param[in] RgSchCellCb *cell
137 * @param[in] RgSchUeCb *ue
138 * @param[in] RgrUeCfg *ueCfg
145 PUBLIC S16 rgSCHMeasGapANRepUeCfg
152 PUBLIC S16 rgSCHMeasGapANRepUeCfg(cell, ue, ueCfg)
159 TRC2(rgSCHMeasGapANRepUeCfg);
162 ue->measGapCb.isMesGapEnabled = ueCfg->ueMesGapCfg.isMesGapEnabled;
164 if (ueCfg->ueMesGapCfg.isMesGapEnabled)
166 ue->measGapCb.gapPrd = ueCfg->ueMesGapCfg.gapPrd;
167 ue->measGapCb.gapOffst = ueCfg->ueMesGapCfg.gapOffst;
168 rgSCHMeasGapANRepUtlAddUe (cell, ue, &(ueCfg->ueMesGapCfg));
169 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
170 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
171 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
174 /* ACK NACK repetition part */
175 if (ueCfg->ueAckNackCfg.isAckNackEnabled)
177 ue->ackNakRepCb.cfgRepCnt = ueCfg->ueAckNackCfg.ackNackRepFactor;
178 ue->ackNakRepCb.repCntr = ue->ackNakRepCb.cfgRepCnt;
179 ue->ackNakRepCb.isAckNackEnabled = TRUE;
180 ue->ackNakRepCb.pucchRes = ueCfg->ueAckNackCfg.pucchAckNackRep;
181 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
182 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
183 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
189 * @brief Handles Measurement gap and ack-nack repetition related
190 * re-configuration for a UE.
194 * Function : rgSCHMeasGapANRepUeRecfg
196 * Invoking Module Processing:
197 * - This shall be invoked by SCH_GOM at UE re-configuration. It shall do the
198 * validations for the spec-defined values.
201 * - For measurement gap,
202 * - If measurement gap period or offset is re-configured, remove UE from
203 * the previous list, if any and add it to the new list.
204 * - Update configured values appropriately.
205 * - For ACK-NACK repetition,
206 * - Update the configured value. Set 'cfgRepCnt' variable value.
207 * - If (repCntr == 0)
208 * - repCntr = cfgRepCnt.
209 * - qOffst = RG_INVALID_ACKNACKREPQ_ID
211 * @param[in] RgSchCellCb *cell
212 * @param[in] RgSchUeCb *ue
213 * @param[in] RgrUeRecfg *ueRecfg
221 PUBLIC S16 rgSCHMeasGapANRepUeRecfg
228 PUBLIC S16 rgSCHMeasGapANRepUeRecfg(cell, ue, ueRecfg)
234 RgrUeMeasGapCfg *reCfg;
235 RgSchUeMeasGapCb *ueMeasCb;
236 RgrUeAckNackRepCfg *ackNackReCfg = &(ueRecfg->ueAckNackRecfg);
237 RgSchUeAckNakRepCb *ackNakRepCb = &(ue->ackNakRepCb);
239 TRC2(rgSCHMeasGapANRepUeRecfg);
242 reCfg = &(ueRecfg->ueMeasGapRecfg);
243 ueMeasCb = &(ue->measGapCb);
245 /* Removed extra comments
246 * Check this once again Check to see if anything changed or not */
247 if ((reCfg->isMesGapEnabled == TRUE) &&
248 (ueMeasCb->isMesGapEnabled == TRUE) &&
249 (reCfg->gapPrd == ueMeasCb->gapPrd) &&
250 (reCfg->gapOffst == ueMeasCb->gapOffst))
252 /* Nothing changed hence nothing to do */
256 if (reCfg->isMesGapEnabled)
258 if (ueMeasCb->isMesGapEnabled)
260 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
264 cmInitTimers (&ueMeasCb->measGapTmr, 1);
265 cmInitTimers (&ueMeasCb->measGapUlInactvTmr, 1);
266 cmInitTimers (&ueMeasCb->measGapDlInactvTmr, 1);
269 /* Add to the correct Measurement gap queue */
270 rgSCHMeasGapANRepUtlAddUe (cell, ue, reCfg);
272 ueMeasCb->gapPrd = reCfg->gapPrd;
273 ueMeasCb->gapOffst = reCfg->gapOffst;
274 ueMeasCb->isMesGapEnabled = TRUE;
275 } /* if new config has Measurement gap enabled */
278 if (ueMeasCb->isMesGapEnabled)
280 /* check if return value needed or not */
281 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
282 ueMeasCb->isMesGapEnabled = FALSE;
284 } /* if new config has Measurement gap disabled */
285 } /* For MeasGap configuration */
287 if (ackNackReCfg->isAckNackEnabled)
289 if (!ackNakRepCb->isAckNackEnabled)
291 ackNakRepCb->isAckNackEnabled = TRUE;
292 /* Timers need to be init immediately after config*/
293 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
294 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
295 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
296 } /* repetition was disabled */
297 ackNakRepCb->pucchRes = ackNackReCfg->pucchAckNackRep;
298 ackNakRepCb->cfgRepCnt = ackNackReCfg->ackNackRepFactor;
299 if (ackNakRepCb->repCntr == 0)
301 ackNakRepCb->repCntr = ackNackReCfg->ackNackRepFactor;
303 } /* repetition enabled in re configuration */
306 ackNakRepCb->isAckNackEnabled = FALSE;
307 } /* repetition disabled in re configuration */
312 /** @brief This function is a utility to add the UE to the correct Measurement
313 * queue present in the cellCb.
328 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe
335 PRIVATE S16 rgSCHMeasGapANRepUtlAddUe (cell, ue, cfg)
338 RgrUeMeasGapCfg *cfg;
342 TRC2(rgSCHMeasGapANRepUtlAddUe);
346 case RG_MEAS_GAPPRD_40:
347 /* Insert the UE into the linked list based on the gap Offset */
348 ue->measGapCb.measQLnk.node = (PTR)ue;
349 cmLListAdd2Tail (&(cell->measGapCb.gapPrd40Q[cfg->gapOffst]),
350 &(ue->measGapCb.measQLnk));
352 case RG_MEAS_GAPPRD_80:
353 ue->measGapCb.measQLnk.node = (PTR)ue;
354 cmLListAdd2Tail (&(cell->measGapCb.gapPrd80Q[cfg->gapOffst]),
355 &(ue->measGapCb.measQLnk));
358 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
359 "rgSCHMeasGapANRepUeRecfg() Incorrect GAP Period"
360 "CRNTI:%d",ue->ueId);
364 } /* end of rgSCHMeasGapANRepUtlAddUe */
367 /** @brief This function is a utility function to remove the ue from the measQ
368 * preset in tthe cell Cb.
382 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe
388 PRIVATE S16 rgSCHMeasGapANRepUtlRmvUe (cell, ue)
394 TRC2(rgSCHMeasGapANRepUtlRmvUe);
396 switch (ue->measGapCb.gapPrd)
398 case RG_MEAS_GAPPRD_40:
399 /* Remove from the existing list */
400 cmLListDelFrm (&(cell->measGapCb.gapPrd40Q[ue->measGapCb.gapOffst]),
401 &(ue->measGapCb.measQLnk));
402 ue->measGapCb.measQLnk.node = NULLP;
404 case RG_MEAS_GAPPRD_80:
405 /* Remove from the existing list */
406 cmLListDelFrm (&(cell->measGapCb.gapPrd80Q[ue->measGapCb.gapOffst]),
407 &(ue->measGapCb.measQLnk));
408 ue->measGapCb.measQLnk.node = NULLP;
412 } /* end of rgSCHMeasGapANRepUtlRmvUe */
415 * @brief Frees Measurement gap and ack-nack repetition related data structures in UE
419 * Function : rgSCHMeasGapANRepUeDel
421 * Invoking Module Processing:
422 * - This shall be invoked by SCH_GOM at Ue deletion.
425 * - For measurement gap,
426 * - if (measGapOffst != RG_INVALID_MEASGAPQ_ID)
427 * - Remove from the measurement queue depending on the measGapPrd
429 * - Delete all timers
430 * - For ACK-NACK repetition,
431 * - if (qOffst != RG_INVALID_ACKNACKREPQ_ID)
432 * - Remove from the ackNakRepQ queue
433 * - Delete all timers
436 * @param[in] RgSchCellCb *cell
437 * @param[in] RgSchUeCb *ue
444 PUBLIC Void rgSCHMeasGapANRepUeDel
451 PUBLIC Void rgSCHMeasGapANRepUeDel(cell, ue, isUeDel)
459 TRC2(rgSCHMeasGapANRepUeDel);
461 if (ue->measGapCb.isMesGapEnabled)
463 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
464 /* Must stop the timer if its running */
465 if (ue->measGapCb.isMeasuring)
467 rgSCHTmrStopTmr (cell, RG_SCH_TMR_MEASGAP, ue);
470 ue->measGapCb.isMesGapEnabled = FALSE;
473 /* Stop timers if running */
474 if (ue->dl.dlInactvMask)
476 if (ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE)
478 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_MEASGAP, ue);
480 if (ue->dl.dlInactvMask & RG_ACKNAKREP_INACTIVE)
482 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_ACKNACK, ue);
484 ue->dl.dlInactvLnk.node = NULLP;
486 if (ue->ul.ulInactvMask)
488 if (ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE)
490 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_MEASGAP, ue);
492 if (ue->ul.ulInactvMask & RG_ACKNAKREP_INACTIVE)
494 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_ACKNACK, ue);
496 ue->ul.ulInactvLnk.node = NULLP;
499 /* ccpu00133470- Releasing ACKNACK Rep UE Deleted */
500 if (isUeDel & ue->ackNakRepCb.isAckNakRep)
502 rgSCHTmrStopTmr (cell, RG_SCH_TMR_ACKNACK_REP, ue);
503 rgSchAckNackRepUtlRmvUe (cell, ue);
508 /** @brief This function deletes the UEs information related to ACK NACK
516 * - Mainly we need to remove the UEs hqProcs from the ackNackQ(s)
517 * present in the subframes.
525 PRIVATE S16 rgSchAckNackRepUtlRmvUe
531 PRIVATE S16 rgSchAckNackRepUtlRmvUe (cell, ue)
540 RgSchDlHqProcCb *hqP;
543 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
545 TRC3(rgSchAckNackRepUtlRmvUe);
547 for (hqIdx = 0; hqIdx < hqEnt->numHqPrcs; hqIdx++)
549 hqP = &hqEnt->procs[hqIdx];
550 /* Starting from index 1 as index 0 isn't used */
551 for (repIdx = 1; repIdx < ue->ackNakRepCb.cfgRepCnt; repIdx++)
553 for (tbCnt = 0; tbCnt < 2; tbCnt++)
555 if ((hqP->tbInfo[tbCnt].crntSubfrm[repIdx] != NULLP) &&
556 (hqP->tbInfo[tbCnt].anRepLnk[repIdx].node != NULLP))
558 cmLListDelFrm(&((hqP->tbInfo[tbCnt].crntSubfrm[repIdx])->\
559 ackNakRepQ), &hqP->tbInfo[tbCnt].anRepLnk[repIdx]);
560 hqP->tbInfo[tbCnt].anRepLnk[repIdx].node = NULLP;
561 hqP->tbInfo[tbCnt].crntSubfrm[repIdx] = NULLP;
572 * @brief Per TTI processing for measurement gap and ack nack repetition
577 * Function : rgSCHMeasGapANRepTtiHndl
579 * Invoking Module Processing:
580 * - This shall be invoked by SCH_TOM on recieving TTI indication from PHY
581 * . SCH_TOM shall update the cell->crntTime before invoking this API.
584 * - Compute qOffset for 40ms queue as =
585 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_40.
586 * - Mark all the UEs at computed offset for performing measurement. Set
587 * isMeasuring = TRUE.
588 * - Start measGapTmr for each UE:
589 * - length = RG_MEAS_GAP_LEN.
590 * - event = RG_MEASGAP_ON
591 * - handler = rgSCHMeasGapANRepTmrExpry
592 * - Reinitalize the list at the offset.
593 * - Compute qOffset for 80ms queue as =
594 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_80.
595 * - Mark all the UEs at computed offset for performing measurement. Set
596 * isMeasuring = TRUE.
597 * - Start measGapTmr for each UE:
598 * - length = RG_MEAS_GAP_LEN.
599 * - event = RG_MEASGAP_ON
600 * - handler = rgSCHMeasGapANRepTmrExpry
601 * - Reinitalize the list at the offset.
602 * - Compute qOffset for ACK NACK repetition queue as =
603 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MAX_NUM_DLSF.
604 * - Mark all the UEs at computed offset for performing ack-nack repetition. Set
605 * isAckNakRep = TRUE.
606 * - Start ackNakRepTmr for each UE:
607 * - length = repCntr.
608 * - event = RG_ACKNAKREP_ON
609 * - handler = rgSchAckNakRepTmrExpry
610 * - Reinitalize the list at the offset.
611 * - 'isMeasuring' bool value shall be cheked
612 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
613 * and if 'TRUE', no dataRecpReq shall be sent.
614 * - While sending NACK as feedback to UE and if 'TRUE' no PHICH shall
615 * be sent and shall mark the UE for adaptive re-tx.
616 * - While sending HqFbkRecpReq for a UE (applicable only if ACK NACK
617 * repetition coincides) and if 'TRUE',
618 * - The request shall not be sent.
619 * - Decrement repCntr
620 * - if (repCntr == 0)
621 * - Delete UE from the list.
622 * - Move the Ue to next subframe's list of ACK-NACK repeating UEs.
623 * - 'isAckNakRep' bool value shall be cheked
624 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
625 * and if 'TRUE', no dataRecpReq shall be sent.
626 * - Check if any refresh for these cell-specific queues is needed
627 * anywhere else as well.
628 * - Check if TTI miss needs some trigger to the module.
631 * @param[in] RgSchCellCb *cell
638 PUBLIC S16 rgSCHMeasGapANRepTtiHndl
643 PUBLIC S16 rgSCHMeasGapANRepTtiHndl(cell)
650 CmLteTimingInfo repTime;
652 TRC2(rgSCHMeasGapANRepTtiHndl);
654 /* Measurement GAP Starts at offSet - however at MAC we are concerned at
655 * subframe + TFU_DELTA.
658 /* Introduced timing delta for DL control in FDD */
660 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + TFU_DELTA) %
663 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + TFU_DLCNTRL_DLDELTA) %
666 queue = &(cell->measGapCb.gapPrd40Q[offset]);
667 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
669 /* Introduced timing delta for DL control in FDD */
671 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + TFU_DELTA) %
674 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + TFU_DLCNTRL_DLDELTA) %
677 queue = &(cell->measGapCb.gapPrd80Q[offset]);
678 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
680 /* for ACK NACK repetition starts at offset - however at MAC we are
681 * concerned with subframe - TFU_DELTA */
682 /* offset = ((cell->crntTime.sfn * 10) + cell->crntTime.subframe) %
683 * RG_MAX_NUM_DLSF; */
684 /* We wish to get the subframe whose HARQ Reception request would go out in
685 * this subframe. HARQ_RTT - TFU_DELTA
687 /* Introduced timing delta for reception req */
690 //RGSCHSUBFRMCRNTTIME(cell->crntTime, repTime, (4 - TFU_DELTA));
691 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
693 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
695 dlSf = rgSCHUtlSubFrmGet (cell, repTime);
696 queue = &(dlSf->ueLst);
697 rgSchAckNackRepUtlHdlTti (cell, queue);
702 /** @brief This function Marks the UE as ackNakRep so that Reception request
703 * isnt sent for any other thing than HARQ.
710 * - Loop through HARQ procs of the DlSf.
711 * - If the UE is a repeating one
712 * - Mark as ackNakRep = TRUE
715 * @param RgSchCellCb *cell
716 * @param CmLListCp *ackNakRepQ
720 PRIVATE Void rgSchAckNackRepUtlHdlTti
723 CmLListCp *ackNackRepQ
726 PRIVATE Void rgSchAckNackRepUtlHdlTti (cell, ackNackRepQ)
728 CmLListCp *ackNackRepQ;
734 TRC2(rgSchAckNackRepUtlHdlTti);
736 node = ackNackRepQ->first;
739 ue = (RgSchUeCb *)(node->node);
740 if ((NULLP != ue) && (ue->ackNakRepCb.isAckNackEnabled))
742 ue->ackNakRepCb.isAckNakRep = TRUE;
743 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_ACKNACK_REP,
744 ue->ackNakRepCb.repCntr);
752 /** @brief This function
767 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti
773 PRIVATE Void rgSCHMeasGapANRepUtlHdlTti (cell, measGapQ)
781 TRC2(rgSCHMeasGapANRepUtlHdlTti);
783 node = measGapQ->first;
786 ue = (RgSchUeCb*)node->node;
787 ue->measGapCb.isMeasuring = TRUE;
788 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_MEASGAP, RG_SCH_MEAS_GAP_LEN);
796 * @brief Determines the list of UEs inactive for DL scheduling due to
797 * measurement gap and ack nack repetitions
801 * Function : rgSCHMeasGapANRepGetDlInactvUe
803 * Invoking Module Processing:
804 * - This API shall be invoked to get list of inactive UEs for downlink
805 * scheduling due to measurement gaps and ACK NACK repetitions.
808 * - Compute qOffset for 40ms or 80ms queue as =
809 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
810 * RG_SCH_CMN_HARQ_INTERVAL)
811 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
812 * - Add all the UEs at computed offset to dlInactvUeLst since the
813 * DL transmission or feedback transmission from UE for DL
814 * transmissions shall collide with measurement gap.
815 * - Mark each UE. Set dlInactvMask |= RG_MEASGAP_INACTIVE
816 * - Start measGapDlInactvTmr timer for each UE,
817 * - length = RG_MEAS_GAP_LEN + RG_SCH_CMN_HARQ_INTERVAL
818 * - event = RG_MEASGAP_DLINACTV
819 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
820 * - Compute qOffset for ACK NACK repetition queue as =
821 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
822 * RG_SCH_CMN_HARQ_INTERVAL -1)
824 * - Add all the UEs at computed offset to dlInactvUeLst since the
825 * feedback transmission from UE for DL transmissions shall
826 * collide with ACK NACK repetition of the UE.
827 * - Mark each UE. Set dlInactvMask |= RG_ACKNAKREP_INACTIVE
828 * - Start ackNakRepDlInactvTmr timer for each UE,
829 * - length = repCntr - 1
830 * - event = RG_ACKNAKREP_DLINACTV
831 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
832 * - Verify the above computations before coding
836 * @param[in] RgSchCellCb *cell
837 * @param[out] CmLListCp *dlInactvUeLst
842 PUBLIC S16 rgSCHMeasGapANRepGetDlInactvUe
845 CmLListCp *dlInactvUeLst
848 PUBLIC S16 rgSCHMeasGapANRepGetDlInactvUe(cell, dlInactvUeLst)
850 CmLListCp *dlInactvUeLst;
859 CmLteTimingInfo ackNakTime;
865 RgSchDlHqProcCb *hqP;
869 TRC2(rgSCHMeasGapANRepGetDlInactvUe);
871 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + RG_DL_DELTA;
874 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
875 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
876 RG_SCH_TDD_DL_SUBFRAME)
881 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
882 if(dlSf->dlFdbkInfo.sfnOffset > 0)
885 (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES+ \
886 RGSCH_NUM_SUB_FRAMES - ackNakTime.subframe + \
887 dlSf->dlFdbkInfo.subframe;
891 harqFdbkOffset = dlSf->dlFdbkInfo.subframe - ackNakTime.subframe;
894 harqFdbkOffset = RG_SCH_CMN_HARQ_INTERVAL;
896 /* Calc offset for Measurement gap 40 */
897 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_40;
898 queue = &(cell->measGapCb.gapPrd40Q[offset]);
903 ue = (RgSchUeCb*)node->node;
904 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
905 /* Add to the inactv list */
906 ue->dl.dlInactvLnk.node = (PTR)ue;
907 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
909 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
910 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
914 /* Calc offset for Measurement gap 80 */
915 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_80;
916 queue = &(cell->measGapCb.gapPrd80Q[offset]);
921 ue = (RgSchUeCb*)node->node;
922 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
923 /* Add to the inactv list */
924 ue->dl.dlInactvLnk.node = (PTR)ue;
925 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
927 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
928 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
932 /* Calc offset for ACK NACK repetition */
933 /*offset = (cell->crntTime.sfn * 10 +
934 cell->crntTime.subframe + RG_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL - 1)
936 /* The ackNakRepQ resides in each dlSf corresponding to the repStart */
937 /* Must pick up the subframe that was scheduled in the last TTI */
939 if(cell->ulDlCfgIdx == 5)
943 rgSCHUtlGetPrevDlSfInfo(cell, ackNakTime, &ackNakTime, &repCntr);
944 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
945 /* crnt DL subframe */
946 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
950 /* Go to the subframe being scheduled */
951 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
952 /* Go to the previous subframe */
953 RGSCHDECRFRMCRNTTIME(ackNakTime, ackNakTime, 1);
957 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime,
960 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
962 queue = &(dlSf->ueLst);
967 ue = (RgSchUeCb *)(node->node);
969 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
972 hqP = (RgSchDlHqProcCb *)hqNode->node;
973 hqNode = hqNode->next;
974 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
976 tbCb = &hqP->tbInfo[i];
977 if (tbCb->fbkRepCntr > 0)
979 ue->dl.dlInactvMask |= RG_ACKNAKREP_INACTIVE;
980 /* Check if already added to the list */
981 if (!(ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE))
983 /* Add to the inactv list */
984 ue->dl.dlInactvLnk.node = (PTR)ue;
985 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
989 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
990 (U8)(ue->ackNakRepCb.repCntr - 1));
991 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK, repCntr);
993 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK,
994 (ue->ackNakRepCb.repCntr - 1));
1004 * @brief Determines the list of UEs inactive for UL scheduling due to
1005 * measurement gap and ack nack repetitions
1009 * Function : rgSCHMeasGapANRepGetUlInactvUe
1011 * Invoking Module Processing:
1012 * - This API shall be invoked to get list of inactive UEs for uplink
1013 * scheduling due to measurement gaps and ACK NACK repetitions.
1016 * - Compute qOffset for 40ms or 80ms queue as =
1017 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
1018 * RG_SCH_CMN_HARQ_INTERVAL)
1019 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
1020 * - Add all the UEs at computed offset to ulInactvUeLst since the UL
1021 * transmissions shall collide with measurement gap.
1022 * - Mark each UE. Set ulInactvMask |= RG_MEASGAP_INACTIVE
1023 * - Start measGapUlInactvTmr timer for each UE
1024 * - length = RG_MEAS_GAP_LEN
1025 * - event = RG_MEASGAP_ULINACTV
1026 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
1027 * - Compute qOffset for ACK NACK repetition queue as =
1028 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
1029 * RG_SCH_CMN_HARQ_INTERVAL)
1030 * % RG_MAX_NUM_DLSF.
1031 * - Add all the UEs at computed offset to ulInactvUeLst since the
1032 * feedback transmission from UE for DL transmissions shall
1033 * collide with repeating ACK ACK-NACKs.
1034 * - Mark each UE. Set ulInactvMask |= RG_ACKNAKREP_INACTIVE
1035 * - Start ackNakRepUlInactv timer for each UE
1036 * - length = repCntr
1037 * - event = RG_ACKNAKREP_ULINACTV
1038 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
1039 * - Verify the above computations before coding
1042 * @param[in] RgSchCellCb *cell
1043 * @param[out] CmLListCp *ulInactvUeLst
1049 PUBLIC S16 rgSCHMeasGapANRepGetUlInactvUe
1052 CmLListCp *ulInactvUeLst
1055 PUBLIC S16 rgSCHMeasGapANRepGetUlInactvUe(cell, ulInactvUeLst)
1057 CmLListCp *ulInactvUeLst;
1066 CmLteTimingInfo ackNakTime;
1074 RgSchDlHqProcCb *hqP;
1075 RgSchDlHqTbCb *tbCb;
1078 TRC2(rgSCHMeasGapANRepGetUlInactvUe);
1080 /*ccpu00139481- Meas Gap should be monitored in UL with TFU_ULCNTRL_DLDELTA*/
1081 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.subframe + \
1082 TFU_ULCNTRL_DLDELTA;
1084 pdcchToPuschGap = RGSCH_PDCCH_PUSCH_DELTA;
1086 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_ULCNTRL_DLDELTA);
1087 pdcchToPuschGap = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][ackNakTime.subframe];
1088 for(idx=0; pdcchToPuschGap && (idx< (pdcchToPuschGap+RG_SCH_MEAS_GAP_LEN)) ; idx++)
1091 /* Calc offset for Measurement gap 40 */
1092 offset = (schedTime + pdcchToPuschGap -idx + RG_MEAS_GAPPRD_40) % RG_MEAS_GAPPRD_40;
1093 queue = &(cell->measGapCb.gapPrd40Q[offset]);
1094 node = queue->first;
1097 ue = (RgSchUeCb*)node->node;
1098 if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1100 ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
1101 /* Add to the inactv list */
1102 ue->ul.ulInactvLnk.node = (PTR)ue;
1103 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1104 /* Start timer Note the timer is started for a value GAP_LEN +
1105 * RG_SCH_CMN_HARQ_INTERVAL. The "4"
1106 * is added because for UE to transmit, the PDCCH must be sent 4 subframes
1107 * ahead - UE cant read PDCCH format0 if it is in measurement gap. */
1108 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1109 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1110 //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);
1115 /* Calc offset for Measurement gap 80 */
1116 offset = (schedTime + pdcchToPuschGap - idx + RG_MEAS_GAPPRD_80) % RG_MEAS_GAPPRD_80;
1117 queue = &(cell->measGapCb.gapPrd80Q[offset]);
1119 node = queue->first;
1122 ue = (RgSchUeCb*)node->node;
1123 if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1125 ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
1126 /* Add to the inactv list */
1127 ue->ul.ulInactvLnk.node = (PTR)ue;
1128 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1130 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1131 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1132 //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);
1137 /* Calc offset for ACK NACK repetition */
1138 /*offset = (cell->crntTime.sfn * 10 +
1139 cell->crntTime.subframe + RG_UL_SCHED_DELTA +
1140 RG_SCH_CMN_HARQ_INTERVAL ) % RG_MAX_NUM_DLSF;*/
1142 /* Must get the DLSF that is scheduled at TFU_DELTA Away */
1144 if(cell->ulDlCfgIdx == 5)
1148 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DELTA);
1149 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
1150 RG_SCH_TDD_DL_SUBFRAME)
1155 /* Introduced timing delta for DL control in FDD */
1156 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DLCNTRL_DLDELTA);
1158 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
1159 queue = &(dlSf->ueLst);
1161 node = queue->first;
1164 ue = (RgSchUeCb *)(node->node);
1166 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
1169 hqP = (RgSchDlHqProcCb *)hqNode->node;
1170 hqNode = hqNode->next;
1171 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1173 tbCb = &hqP->tbInfo[i];
1174 if (tbCb->fbkRepCntr > 0)
1176 ue->ul.ulInactvMask |= RG_ACKNAKREP_INACTIVE;
1177 /* Check if already added to the list */
1178 if (!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1180 /* Add to the inactv list */
1181 ue->ul.ulInactvLnk.node = (PTR)ue;
1182 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1186 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
1187 ue->ackNakRepCb.repCntr);
1188 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK, repCntr);
1190 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK,
1191 (ue->ackNakRepCb.repCntr));
1201 * @brief Handles processing of DL Inactive timer expiry at the end of
1202 * measurement gap or ack nack repetition for a UE
1206 * Function : rgSCHMeasGapANRepDlInactvTmrExpry
1208 * Invoking Module Processing:
1209 * - This API shall be invoked to process DL inactive timer expiry
1212 * - If timer event is RG_MEASGAP_DLINACTV,
1213 * - dlInactvMask &= ~RG_MEASGAP_INACTIVE
1214 * - If timer event is RG_ACKNAKREP_DLINACTV,
1215 * - dlInactvMask &= ~RG_ACKNAKREP_INACTIVE
1216 * - if (!dlInactvMask)
1217 * - Invoke DL scheduler to put the UE back into the scheduling queues.
1218 * - Re-initialize timer.
1221 * @param[in] RgSchUeCb *ue
1222 * @param[in] Check if some timer related parameter needs to be passed
1228 PUBLIC Void rgSCHMeasGapANRepDlInactvTmrExpry
1234 PUBLIC Void rgSCHMeasGapANRepDlInactvTmrExpry(ue, tmrEvnt)
1240 RgSchCellCb *cell = ue->cell;
1241 TRC2(rgSCHMeasGapANRepDlInactvTmrExpry);
1245 case RG_SCH_TMR_DL_MEASGAP:
1246 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1248 case RG_SCH_TMR_DL_ACKNACK:
1249 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1252 if (!ue->dl.dlInactvMask)
1254 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
1255 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
1261 * @brief Handles processing of UL Inactive timer expiry at the end of
1262 * measurement gap or ack nack repetition for a UE
1266 * Function : rgSCHMeasGapANRepUlInactvTmrExpry
1268 * Invoking Module Processing:
1269 * - This API shall be invoked to process UL inactive timer expiry
1272 * - If timer event is RG_MEASGAP_ULINACTV,
1273 * - ulInactvMask &= ~RG_MEASGAP_INACTIVE
1274 * - If timer event is RG_ACKNAKREP_ULINACTV,
1275 * - ulInactvMask &= ~RG_ACKNAKREP_INACTIVE
1276 * - if (!ulInactvMask)
1277 * - Invoke UL scheduler to put the UE back into the scheduling queues.
1278 * - Re-initialize timer.
1281 * @param[in] RgSchUeCb *ue
1282 * @param[in] Check if some timer related parameter needs to be passed
1288 PUBLIC Void rgSCHMeasGapANRepUlInactvTmrExpry
1294 PUBLIC Void rgSCHMeasGapANRepUlInactvTmrExpry(ue, tmrEvnt)
1299 RgSchCellCb *cell = ue->cell;
1300 TRC2(rgSCHMeasGapANRepUlInactvTmrExpry);
1304 case RG_SCH_TMR_UL_MEASGAP:
1305 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1307 case RG_SCH_TMR_UL_ACKNACK:
1308 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1311 if (!ue->ul.ulInactvMask)
1313 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
1314 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
1320 * @brief Handles processing of measurement gap timer expiry at the end of
1325 * Function : rgSCHMeasGapANRepTmrExpry
1327 * Invoking Module Processing:
1328 * - This API shall be invoked to process measurement gap timer expiry
1331 * - Set ue->isMeasuring = FALSE
1332 * - Re-initialize timer.
1335 * @param[in] RgSchUeCb *ue
1336 * @param[in] Check if some timer related parameter needs to be passed
1342 PUBLIC Void rgSCHMeasGapANRepTmrExpry
1347 PUBLIC Void rgSCHMeasGapANRepTmrExpry(ue)
1352 TRC2(rgSCHMeasGapANRepTmrExpry);
1354 ue->measGapCb.isMeasuring = FALSE;
1355 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
1361 * @brief Handles processing of ACK-NACK repetition timer expiry at the end of
1362 * ACK-NACK repetition.
1366 * Function : rgSchAckNakRepTmrExpry
1368 * Invoking Module Processing:
1369 * - This API shall be invoked to process ACK-NACK repetition timer expiry
1372 * - Set ue->isAckNakRep = FALSE
1373 * - Re-initialize timer.
1376 * @param[in] RgSchUeCb *ue
1377 * @param[in] Check if some timer related parameter needs to be passed
1383 PUBLIC Void rgSCHAckNakRepTmrExpry
1388 PUBLIC Void rgSCHAckNakRepTmrExpry(ue)
1393 TRC2(rgSCHAckNakRepTmrExpry);
1395 ue->ackNakRepCb.isAckNakRep = FALSE;
1396 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
1403 * @brief Adds ACK-NACK repeating UEs to the ackNakRepQ
1407 * Function : rgSchAckNakRepAddToQ
1409 * Invoking Module Processing:
1410 * - This API shall be invoked for adding list of UEs to the ACK-NACK
1411 * repeating queue at appropriate poistion. Invoking module shall invoke
1412 * with the list of ACK-NACK repeating UEs for a sub-frame and timing info
1413 * at which ACK NACK repetition shall start for the UEs.
1416 * - Determine the qOffset depending on the timing info as
1417 * - qOffset = (repStartTime->sfn *10 + repStartTime->subframe) % RG_MAX_NUM_DLSF
1418 * - Initialize the list at the qOffset.
1419 * - For each UE in the list,
1420 * - Add the UE to ackNakRepQ to the list at the determined qOffset.
1421 * - Set ue->qOffset = qOffset
1422 * - Initialize timers.
1425 * @param[in] RgSchCellCb *cell
1426 * @param[in] RgSchDlSf *crntDlSf
1427 * @param[in] CmLteTimingInfo repStartTime
1434 PUBLIC Void rgSCHAckNakRepAddToQ
1440 PUBLIC Void rgSCHAckNakRepAddToQ(cell, crntDlSf)
1442 RgSchDlSf *crntDlSf;
1448 RgSchDlHqProcCb *hqP;
1449 RgSchDlHqTbCb *tbCb;
1452 TRC2(rgSCHAckNakRepAddToQ);
1454 node = crntDlSf->ueLst.first;
1457 ue = (RgSchUeCb *)(node->node);
1459 hqNode = ue->dl.dlSfHqInfo[cell->cellId][crntDlSf->dlIdx].hqPLst.first;
1462 hqP = (RgSchDlHqProcCb *)hqNode->node;
1463 hqNode = hqNode->next;
1464 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1466 tbCb = &hqP->tbInfo[i];
1467 /* Add UEs that have enabled ACK NACK repetition */
1468 if (ue->ackNakRepCb.isAckNackEnabled)
1470 tbCb->fbkRepCntr = ue->ackNakRepCb.cfgRepCnt;
1471 tbCb->fbkRecpRepCntr = ue->ackNakRepCb.cfgRepCnt;
1472 /* Removed init of timers as the init will be happening during
1473 * config or timer expiry*/
1484 * @brief Finds the number of subframes used for ACK-NACK cycle
1488 * Function : rgSCHAckNakRepFindUlDuration
1490 * This function finds the number of subframes required
1491 * for ACK-NACK repetition cycle based on UL subframes.
1493 * @param[in] RgSchCellCb *cell
1494 * @param[in] RgSchDlSf *dlSf
1495 * @param[in] CmLteTimingInfo repTime
1496 * @param[in] U8 repCnt
1503 PRIVATE U8 rgSCHAckNakRepFindUlDuration
1507 CmLteTimingInfo repTime,
1511 PRIVATE U8 rgSCHAckNakRepFindUlDuration(cell, dlSf, repTime, repCnt)
1514 CmLteTimingInfo repTime;
1518 CmLteTimingInfo ulfrm;
1520 U16 ulDlCfgIdx = cell->ulDlCfgIdx;
1525 TRC2(rgSCHAckNakRepFindUlDuration)
1526 rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, repTime, &noSubfrms);
1527 RG_SCH_ADD_TO_CRNT_TIME(repTime, ulfrm, noSubfrms);
1529 idx = ulfrm.subframe;
1532 idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
1533 if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] ==
1534 RG_SCH_TDD_UL_SUBFRAME)
1542 RETVALUE(noSubfrms);
1546 * @brief Finds the number of subframes used for ACK-NACK cycle
1550 * Function : rgSCHAckNakRepGetUlOffsetFrmDl
1552 * This function finds the number of subframes after
1553 * which UL subframes are present for the gicen DL
1556 * @param[in] RgSchDlSf *dlSf
1557 * @param[in] CmLteTimingInfo crntDlTime
1558 * @param[in] U8 *noSubfrms
1565 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl
1568 CmLteTimingInfo crntDlTime,
1572 PRIVATE Void rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, crntDlTime, noSubfrms)
1574 CmLteTimingInfo crntDlTime;
1578 TRC2(rgSCHAckNakRepGetUlOffsetFrmDl)
1580 if(dlSf->dlFdbkInfo.sfnOffset != 0)
1582 *noSubfrms = (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES;
1583 *noSubfrms = *noSubfrms + RGSCH_NUM_SUB_FRAMES - crntDlTime.subframe;
1584 *noSubfrms = *noSubfrms + dlSf->dlFdbkInfo.subframe;
1588 *noSubfrms = dlSf->dlFdbkInfo.subframe - crntDlTime.subframe;
1594 /**********************************************************************
1597 **********************************************************************/