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 static S16 rgSCHMeasGapANRepUtlAddUe ARGS((
62 RgrUeMeasGapCfg *cfg));
64 static S16 rgSCHMeasGapANRepUtlRmvUe ARGS((
68 static S16 rgSchAckNackRepUtlRmvUe ARGS((
72 static Void rgSchAckNackRepUtlHdlTti ARGS((
74 CmLListCp *ackNackRepQ));
76 static Void rgSCHMeasGapANRepUtlHdlTti ARGS((
78 CmLListCp *measGapQ));
80 static uint8_t rgSCHAckNakRepFindUlDuration ARGS((
83 CmLteTimingInfo repTime,
85 static 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 S16 rgSCHMeasGapANRepUeCfg
135 S16 rgSCHMeasGapANRepUeCfg(cell, ue, ueCfg)
142 ue->measGapCb.isMesGapEnabled = ueCfg->ueMesGapCfg.isMesGapEnabled;
144 if (ueCfg->ueMesGapCfg.isMesGapEnabled)
146 ue->measGapCb.gapPrd = ueCfg->ueMesGapCfg.gapPrd;
147 ue->measGapCb.gapOffst = ueCfg->ueMesGapCfg.gapOffst;
148 rgSCHMeasGapANRepUtlAddUe (cell, ue, &(ueCfg->ueMesGapCfg));
149 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
150 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
151 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
154 /* ACK NACK repetition part */
155 if (ueCfg->ueAckNackCfg.isAckNackEnabled)
157 ue->ackNakRepCb.cfgRepCnt = ueCfg->ueAckNackCfg.ackNackRepFactor;
158 ue->ackNakRepCb.repCntr = ue->ackNakRepCb.cfgRepCnt;
159 ue->ackNakRepCb.isAckNackEnabled = TRUE;
160 ue->ackNakRepCb.pucchRes = ueCfg->ueAckNackCfg.pucchAckNackRep;
161 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
162 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
163 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
169 * @brief Handles Measurement gap and ack-nack repetition related
170 * re-configuration for a UE.
174 * Function : rgSCHMeasGapANRepUeRecfg
176 * Invoking Module Processing:
177 * - This shall be invoked by SCH_GOM at UE re-configuration. It shall do the
178 * validations for the spec-defined values.
181 * - For measurement gap,
182 * - If measurement gap period or offset is re-configured, remove UE from
183 * the previous list, if any and add it to the new list.
184 * - Update configured values appropriately.
185 * - For ACK-NACK repetition,
186 * - Update the configured value. Set 'cfgRepCnt' variable value.
187 * - If (repCntr == 0)
188 * - repCntr = cfgRepCnt.
189 * - qOffst = RG_INVALID_ACKNACKREPQ_ID
191 * @param[in] RgSchCellCb *cell
192 * @param[in] RgSchUeCb *ue
193 * @param[in] RgrUeRecfg *ueRecfg
201 S16 rgSCHMeasGapANRepUeRecfg
208 S16 rgSCHMeasGapANRepUeRecfg(cell, ue, ueRecfg)
214 RgrUeMeasGapCfg *reCfg;
215 RgSchUeMeasGapCb *ueMeasCb;
216 RgrUeAckNackRepCfg *ackNackReCfg = &(ueRecfg->ueAckNackRecfg);
217 RgSchUeAckNakRepCb *ackNakRepCb = &(ue->ackNakRepCb);
219 reCfg = &(ueRecfg->ueMeasGapRecfg);
220 ueMeasCb = &(ue->measGapCb);
222 /* Removed extra comments
223 * Check this once again Check to see if anything changed or not */
224 if ((reCfg->isMesGapEnabled == TRUE) &&
225 (ueMeasCb->isMesGapEnabled == TRUE) &&
226 (reCfg->gapPrd == ueMeasCb->gapPrd) &&
227 (reCfg->gapOffst == ueMeasCb->gapOffst))
229 /* Nothing changed hence nothing to do */
233 if (reCfg->isMesGapEnabled)
235 if (ueMeasCb->isMesGapEnabled)
237 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
241 cmInitTimers (&ueMeasCb->measGapTmr, 1);
242 cmInitTimers (&ueMeasCb->measGapUlInactvTmr, 1);
243 cmInitTimers (&ueMeasCb->measGapDlInactvTmr, 1);
246 /* Add to the correct Measurement gap queue */
247 rgSCHMeasGapANRepUtlAddUe (cell, ue, reCfg);
249 ueMeasCb->gapPrd = reCfg->gapPrd;
250 ueMeasCb->gapOffst = reCfg->gapOffst;
251 ueMeasCb->isMesGapEnabled = TRUE;
252 } /* if new config has Measurement gap enabled */
255 if (ueMeasCb->isMesGapEnabled)
257 /* check if return value needed or not */
258 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
259 ueMeasCb->isMesGapEnabled = FALSE;
261 } /* if new config has Measurement gap disabled */
262 } /* For MeasGap configuration */
264 if (ackNackReCfg->isAckNackEnabled)
266 if (!ackNakRepCb->isAckNackEnabled)
268 ackNakRepCb->isAckNackEnabled = TRUE;
269 /* Timers need to be init immediately after config*/
270 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
271 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
272 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
273 } /* repetition was disabled */
274 ackNakRepCb->pucchRes = ackNackReCfg->pucchAckNackRep;
275 ackNakRepCb->cfgRepCnt = ackNackReCfg->ackNackRepFactor;
276 if (ackNakRepCb->repCntr == 0)
278 ackNakRepCb->repCntr = ackNackReCfg->ackNackRepFactor;
280 } /* repetition enabled in re configuration */
283 ackNakRepCb->isAckNackEnabled = FALSE;
284 } /* repetition disabled in re configuration */
289 /** @brief This function is a utility to add the UE to the correct Measurement
290 * queue present in the cellCb.
305 static S16 rgSCHMeasGapANRepUtlAddUe
312 static S16 rgSCHMeasGapANRepUtlAddUe (cell, ue, cfg)
315 RgrUeMeasGapCfg *cfg;
321 case RG_MEAS_GAPPRD_40:
322 /* Insert the UE into the linked list based on the gap Offset */
323 ue->measGapCb.measQLnk.node = (PTR)ue;
324 cmLListAdd2Tail (&(cell->measGapCb.gapPrd40Q[cfg->gapOffst]),
325 &(ue->measGapCb.measQLnk));
327 case RG_MEAS_GAPPRD_80:
328 ue->measGapCb.measQLnk.node = (PTR)ue;
329 cmLListAdd2Tail (&(cell->measGapCb.gapPrd80Q[cfg->gapOffst]),
330 &(ue->measGapCb.measQLnk));
333 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
334 "rgSCHMeasGapANRepUeRecfg() Incorrect GAP Period"
335 "CRNTI:%d",ue->ueId);
339 } /* end of rgSCHMeasGapANRepUtlAddUe */
342 /** @brief This function is a utility function to remove the ue from the measQ
343 * preset in tthe cell Cb.
357 static S16 rgSCHMeasGapANRepUtlRmvUe
363 static S16 rgSCHMeasGapANRepUtlRmvUe (cell, ue)
369 switch (ue->measGapCb.gapPrd)
371 case RG_MEAS_GAPPRD_40:
372 /* Remove from the existing list */
373 cmLListDelFrm (&(cell->measGapCb.gapPrd40Q[ue->measGapCb.gapOffst]),
374 &(ue->measGapCb.measQLnk));
375 ue->measGapCb.measQLnk.node = NULLP;
377 case RG_MEAS_GAPPRD_80:
378 /* Remove from the existing list */
379 cmLListDelFrm (&(cell->measGapCb.gapPrd80Q[ue->measGapCb.gapOffst]),
380 &(ue->measGapCb.measQLnk));
381 ue->measGapCb.measQLnk.node = NULLP;
385 } /* end of rgSCHMeasGapANRepUtlRmvUe */
388 * @brief Frees Measurement gap and ack-nack repetition related data structures in UE
392 * Function : rgSCHMeasGapANRepUeDel
394 * Invoking Module Processing:
395 * - This shall be invoked by SCH_GOM at Ue deletion.
398 * - For measurement gap,
399 * - if (measGapOffst != RG_INVALID_MEASGAPQ_ID)
400 * - Remove from the measurement queue depending on the measGapPrd
402 * - Delete all timers
403 * - For ACK-NACK repetition,
404 * - if (qOffst != RG_INVALID_ACKNACKREPQ_ID)
405 * - Remove from the ackNakRepQ queue
406 * - Delete all timers
409 * @param[in] RgSchCellCb *cell
410 * @param[in] RgSchUeCb *ue
417 Void rgSCHMeasGapANRepUeDel
424 Void rgSCHMeasGapANRepUeDel(cell, ue, isUeDel)
431 if (ue->measGapCb.isMesGapEnabled)
433 rgSCHMeasGapANRepUtlRmvUe (cell, ue);
434 /* Must stop the timer if its running */
435 if (ue->measGapCb.isMeasuring)
437 rgSCHTmrStopTmr (cell, RG_SCH_TMR_MEASGAP, ue);
440 ue->measGapCb.isMesGapEnabled = FALSE;
443 /* Stop timers if running */
444 if (ue->dl.dlInactvMask)
446 if (ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE)
448 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_MEASGAP, ue);
450 if (ue->dl.dlInactvMask & RG_ACKNAKREP_INACTIVE)
452 rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_ACKNACK, ue);
454 ue->dl.dlInactvLnk.node = NULLP;
456 if (ue->ul.ulInactvMask)
458 if (ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE)
460 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_MEASGAP, ue);
462 if (ue->ul.ulInactvMask & RG_ACKNAKREP_INACTIVE)
464 rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_ACKNACK, ue);
466 ue->ul.ulInactvLnk.node = NULLP;
469 /* ccpu00133470- Releasing ACKNACK Rep UE Deleted */
470 if (isUeDel & ue->ackNakRepCb.isAckNakRep)
472 rgSCHTmrStopTmr (cell, RG_SCH_TMR_ACKNACK_REP, ue);
473 rgSchAckNackRepUtlRmvUe (cell, ue);
478 /** @brief This function deletes the UEs information related to ACK NACK
486 * - Mainly we need to remove the UEs hqProcs from the ackNackQ(s)
487 * present in the subframes.
495 static S16 rgSchAckNackRepUtlRmvUe
501 static S16 rgSchAckNackRepUtlRmvUe (cell, ue)
510 RgSchDlHqProcCb *hqP;
513 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
515 for (hqIdx = 0; hqIdx < hqEnt->numHqPrcs; hqIdx++)
517 hqP = &hqEnt->procs[hqIdx];
518 /* Starting from index 1 as index 0 isn't used */
519 for (repIdx = 1; repIdx < ue->ackNakRepCb.cfgRepCnt; repIdx++)
521 for (tbCnt = 0; tbCnt < 2; tbCnt++)
523 if ((hqP->tbInfo[tbCnt].crntSubfrm[repIdx] != NULLP) &&
524 (hqP->tbInfo[tbCnt].anRepLnk[repIdx].node != NULLP))
526 cmLListDelFrm(&((hqP->tbInfo[tbCnt].crntSubfrm[repIdx])->\
527 ackNakRepQ), &hqP->tbInfo[tbCnt].anRepLnk[repIdx]);
528 hqP->tbInfo[tbCnt].anRepLnk[repIdx].node = NULLP;
529 hqP->tbInfo[tbCnt].crntSubfrm[repIdx] = NULLP;
540 * @brief Per TTI processing for measurement gap and ack nack repetition
545 * Function : rgSCHMeasGapANRepTtiHndl
547 * Invoking Module Processing:
548 * - This shall be invoked by SCH_TOM on recieving TTI indication from PHY
549 * . SCH_TOM shall update the cell->crntTime before invoking this API.
552 * - Compute qOffset for 40ms queue as =
553 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_40.
554 * - Mark all the UEs at computed offset for performing measurement. Set
555 * isMeasuring = TRUE.
556 * - Start measGapTmr for each UE:
557 * - length = RG_MEAS_GAP_LEN.
558 * - event = RG_MEASGAP_ON
559 * - handler = rgSCHMeasGapANRepTmrExpry
560 * - Reinitalize the list at the offset.
561 * - Compute qOffset for 80ms queue as =
562 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_80.
563 * - Mark all the UEs at computed offset for performing measurement. Set
564 * isMeasuring = TRUE.
565 * - Start measGapTmr for each UE:
566 * - length = RG_MEAS_GAP_LEN.
567 * - event = RG_MEASGAP_ON
568 * - handler = rgSCHMeasGapANRepTmrExpry
569 * - Reinitalize the list at the offset.
570 * - Compute qOffset for ACK NACK repetition queue as =
571 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MAX_NUM_DLSF.
572 * - Mark all the UEs at computed offset for performing ack-nack repetition. Set
573 * isAckNakRep = TRUE.
574 * - Start ackNakRepTmr for each UE:
575 * - length = repCntr.
576 * - event = RG_ACKNAKREP_ON
577 * - handler = rgSchAckNakRepTmrExpry
578 * - Reinitalize the list at the offset.
579 * - 'isMeasuring' bool value shall be cheked
580 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
581 * and if 'TRUE', no dataRecpReq shall be sent.
582 * - While sending NACK as feedback to UE and if 'TRUE' no PHICH shall
583 * be sent and shall mark the UE for adaptive re-tx.
584 * - While sending HqFbkRecpReq for a UE (applicable only if ACK NACK
585 * repetition coincides) and if 'TRUE',
586 * - The request shall not be sent.
587 * - Decrement repCntr
588 * - if (repCntr == 0)
589 * - Delete UE from the list.
590 * - Move the Ue to next subframe's list of ACK-NACK repeating UEs.
591 * - 'isAckNakRep' bool value shall be cheked
592 * - While sending dataRecpReq to PHY for non-adaptive uplink re-tx
593 * and if 'TRUE', no dataRecpReq shall be sent.
594 * - Check if any refresh for these cell-specific queues is needed
595 * anywhere else as well.
596 * - Check if TTI miss needs some trigger to the module.
599 * @param[in] RgSchCellCb *cell
606 S16 rgSCHMeasGapANRepTtiHndl
611 S16 rgSCHMeasGapANRepTtiHndl(cell)
618 CmLteTimingInfo repTime;
620 /* Measurement GAP Starts at offSet - however at MAC we are concerned at
621 * subframe + TFU_DELTA.
624 /* Introduced timing delta for DL control in FDD */
626 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) %
629 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) %
632 queue = &(cell->measGapCb.gapPrd40Q[offset]);
633 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
635 /* Introduced timing delta for DL control in FDD */
637 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) %
640 offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) %
643 queue = &(cell->measGapCb.gapPrd80Q[offset]);
644 rgSCHMeasGapANRepUtlHdlTti (cell, queue);
646 /* for ACK NACK repetition starts at offset - however at MAC we are
647 * concerned with subframe - TFU_DELTA */
648 /* offset = ((cell->crntTime.sfn * 10) + cell->crntTime.slot) %
649 * RG_MAX_NUM_DLSF; */
650 /* We wish to get the subframe whose HARQ Reception request would go out in
651 * this subframe. HARQ_RTT - TFU_DELTA
653 /* Introduced timing delta for reception req */
656 //RGSCHSUBFRMCRNTTIME(cell->crntTime, repTime, (4 - TFU_DELTA));
657 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
659 RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
661 dlSf = rgSCHUtlSubFrmGet (cell, repTime);
662 queue = &(dlSf->ueLst);
663 rgSchAckNackRepUtlHdlTti (cell, queue);
668 /** @brief This function Marks the UE as ackNakRep so that Reception request
669 * isnt sent for any other thing than HARQ.
676 * - Loop through HARQ procs of the DlSf.
677 * - If the UE is a repeating one
678 * - Mark as ackNakRep = TRUE
681 * @param RgSchCellCb *cell
682 * @param CmLListCp *ackNakRepQ
686 static Void rgSchAckNackRepUtlHdlTti
689 CmLListCp *ackNackRepQ
692 static Void rgSchAckNackRepUtlHdlTti (cell, ackNackRepQ)
694 CmLListCp *ackNackRepQ;
700 node = ackNackRepQ->first;
703 ue = (RgSchUeCb *)(node->node);
704 if ((NULLP != ue) && (ue->ackNakRepCb.isAckNackEnabled))
706 ue->ackNakRepCb.isAckNakRep = TRUE;
707 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_ACKNACK_REP,
708 ue->ackNakRepCb.repCntr);
716 /** @brief This function
731 static Void rgSCHMeasGapANRepUtlHdlTti
737 static Void rgSCHMeasGapANRepUtlHdlTti (cell, measGapQ)
745 node = measGapQ->first;
748 ue = (RgSchUeCb*)node->node;
749 ue->measGapCb.isMeasuring = TRUE;
750 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_MEASGAP, RG_SCH_MEAS_GAP_LEN);
758 * @brief Determines the list of UEs inactive for DL scheduling due to
759 * measurement gap and ack nack repetitions
763 * Function : rgSCHMeasGapANRepGetDlInactvUe
765 * Invoking Module Processing:
766 * - This API shall be invoked to get list of inactive UEs for downlink
767 * scheduling due to measurement gaps and ACK NACK repetitions.
770 * - Compute qOffset for 40ms or 80ms queue as =
771 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
772 * RG_SCH_CMN_HARQ_INTERVAL)
773 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
774 * - Add all the UEs at computed offset to dlInactvUeLst since the
775 * DL transmission or feedback transmission from UE for DL
776 * transmissions shall collide with measurement gap.
777 * - Mark each UE. Set dlInactvMask |= RG_MEASGAP_INACTIVE
778 * - Start measGapDlInactvTmr timer for each UE,
779 * - length = RG_MEAS_GAP_LEN + RG_SCH_CMN_HARQ_INTERVAL
780 * - event = RG_MEASGAP_DLINACTV
781 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
782 * - Compute qOffset for ACK NACK repetition queue as =
783 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
784 * RG_SCH_CMN_HARQ_INTERVAL -1)
786 * - Add all the UEs at computed offset to dlInactvUeLst since the
787 * feedback transmission from UE for DL transmissions shall
788 * collide with ACK NACK repetition of the UE.
789 * - Mark each UE. Set dlInactvMask |= RG_ACKNAKREP_INACTIVE
790 * - Start ackNakRepDlInactvTmr timer for each UE,
791 * - length = repCntr - 1
792 * - event = RG_ACKNAKREP_DLINACTV
793 * - handler = rgSCHMeasGapANRepDlInactvTmrExpry
794 * - Verify the above computations before coding
798 * @param[in] RgSchCellCb *cell
799 * @param[out] CmLListCp *dlInactvUeLst
804 S16 rgSCHMeasGapANRepGetDlInactvUe
807 CmLListCp *dlInactvUeLst
810 S16 rgSCHMeasGapANRepGetDlInactvUe(cell, dlInactvUeLst)
812 CmLListCp *dlInactvUeLst;
821 CmLteTimingInfo ackNakTime;
823 uint8_t harqFdbkOffset;
827 RgSchDlHqProcCb *hqP;
831 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + RG_DL_DELTA;
834 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
835 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
836 RG_SCH_TDD_DL_SUBFRAME)
841 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
842 if(dlSf->dlFdbkInfo.sfnOffset > 0)
845 (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES+ \
846 RGSCH_NUM_SUB_FRAMES - ackNakTime.subframe + \
847 dlSf->dlFdbkInfo.subframe;
851 harqFdbkOffset = dlSf->dlFdbkInfo.subframe - ackNakTime.subframe;
854 harqFdbkOffset = RG_SCH_CMN_HARQ_INTERVAL;
856 /* Calc offset for Measurement gap 40 */
857 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_40;
858 queue = &(cell->measGapCb.gapPrd40Q[offset]);
863 ue = (RgSchUeCb*)node->node;
864 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
865 /* Add to the inactv list */
866 ue->dl.dlInactvLnk.node = (PTR)ue;
867 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
869 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
870 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
874 /* Calc offset for Measurement gap 80 */
875 offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_80;
876 queue = &(cell->measGapCb.gapPrd80Q[offset]);
881 ue = (RgSchUeCb*)node->node;
882 ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
883 /* Add to the inactv list */
884 ue->dl.dlInactvLnk.node = (PTR)ue;
885 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
887 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP,
888 (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
892 /* Calc offset for ACK NACK repetition */
893 /*offset = (cell->crntTime.sfn * 10 +
894 cell->crntTime.slot + RG_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL - 1)
896 /* The ackNakRepQ resides in each dlSf corresponding to the repStart */
897 /* Must pick up the subframe that was scheduled in the last TTI */
899 if(cell->ulDlCfgIdx == 5)
903 rgSCHUtlGetPrevDlSfInfo(cell, ackNakTime, &ackNakTime, &repCntr);
904 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
905 /* crnt DL subframe */
906 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
910 /* Go to the subframe being scheduled */
911 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
912 /* Go to the previous subframe */
913 RGSCHDECRFRMCRNTTIME(ackNakTime, ackNakTime, 1);
917 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime,
920 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
922 queue = &(dlSf->ueLst);
927 ue = (RgSchUeCb *)(node->node);
929 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
932 hqP = (RgSchDlHqProcCb *)hqNode->node;
933 hqNode = hqNode->next;
934 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
936 tbCb = &hqP->tbInfo[i];
937 if (tbCb->fbkRepCntr > 0)
939 ue->dl.dlInactvMask |= RG_ACKNAKREP_INACTIVE;
940 /* Check if already added to the list */
941 if (!(ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE))
943 /* Add to the inactv list */
944 ue->dl.dlInactvLnk.node = (PTR)ue;
945 cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
949 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
950 (uint8_t)(ue->ackNakRepCb.repCntr - 1));
951 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK, repCntr);
953 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK,
954 (ue->ackNakRepCb.repCntr - 1));
964 * @brief Determines the list of UEs inactive for UL scheduling due to
965 * measurement gap and ack nack repetitions
969 * Function : rgSCHMeasGapANRepGetUlInactvUe
971 * Invoking Module Processing:
972 * - This API shall be invoked to get list of inactive UEs for uplink
973 * scheduling due to measurement gaps and ACK NACK repetitions.
976 * - Compute qOffset for 40ms or 80ms queue as =
977 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
978 * RG_SCH_CMN_HARQ_INTERVAL)
979 * % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
980 * - Add all the UEs at computed offset to ulInactvUeLst since the UL
981 * transmissions shall collide with measurement gap.
982 * - Mark each UE. Set ulInactvMask |= RG_MEASGAP_INACTIVE
983 * - Start measGapUlInactvTmr timer for each UE
984 * - length = RG_MEAS_GAP_LEN
985 * - event = RG_MEASGAP_ULINACTV
986 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
987 * - Compute qOffset for ACK NACK repetition queue as =
988 * ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
989 * RG_SCH_CMN_HARQ_INTERVAL)
991 * - Add all the UEs at computed offset to ulInactvUeLst since the
992 * feedback transmission from UE for DL transmissions shall
993 * collide with repeating ACK ACK-NACKs.
994 * - Mark each UE. Set ulInactvMask |= RG_ACKNAKREP_INACTIVE
995 * - Start ackNakRepUlInactv timer for each UE
997 * - event = RG_ACKNAKREP_ULINACTV
998 * - handler = rgSCHMeasGapANRepUlInactvTmrExpry
999 * - Verify the above computations before coding
1002 * @param[in] RgSchCellCb *cell
1003 * @param[out] CmLListCp *ulInactvUeLst
1009 S16 rgSCHMeasGapANRepGetUlInactvUe
1012 CmLListCp *ulInactvUeLst
1015 S16 rgSCHMeasGapANRepGetUlInactvUe(cell, ulInactvUeLst)
1017 CmLListCp *ulInactvUeLst;
1026 CmLteTimingInfo ackNakTime;
1029 uint8_t pdcchToPuschGap;
1034 RgSchDlHqProcCb *hqP;
1035 RgSchDlHqTbCb *tbCb;
1038 /*ccpu00139481- Meas Gap should be monitored in UL with TFU_ULCNTRL_DLDELTA*/
1039 schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + \
1040 TFU_ULCNTRL_DLDELTA;
1042 pdcchToPuschGap = RGSCH_PDCCH_PUSCH_DELTA;
1044 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_ULCNTRL_DLDELTA);
1045 pdcchToPuschGap = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][ackNakTime.subframe];
1046 for(idx=0; pdcchToPuschGap && (idx< (pdcchToPuschGap+RG_SCH_MEAS_GAP_LEN)) ; idx++)
1049 /* Calc offset for Measurement gap 40 */
1050 offset = (schedTime + pdcchToPuschGap -idx + RG_MEAS_GAPPRD_40) % RG_MEAS_GAPPRD_40;
1051 queue = &(cell->measGapCb.gapPrd40Q[offset]);
1052 node = queue->first;
1055 ue = (RgSchUeCb*)node->node;
1056 if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1058 ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
1059 /* Add to the inactv list */
1060 ue->ul.ulInactvLnk.node = (PTR)ue;
1061 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1062 /* Start timer Note the timer is started for a value GAP_LEN +
1063 * RG_SCH_CMN_HARQ_INTERVAL. The "4"
1064 * is added because for UE to transmit, the PDCCH must be sent 4 subframes
1065 * ahead - UE cant read PDCCH format0 if it is in measurement gap. */
1066 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1067 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1068 //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);
1073 /* Calc offset for Measurement gap 80 */
1074 offset = (schedTime + pdcchToPuschGap - idx + RG_MEAS_GAPPRD_80) % RG_MEAS_GAPPRD_80;
1075 queue = &(cell->measGapCb.gapPrd80Q[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));
1088 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP,
1089 (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
1090 //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);
1095 /* Calc offset for ACK NACK repetition */
1096 /*offset = (cell->crntTime.sfn * 10 +
1097 cell->crntTime.slot + RG_UL_SCHED_DELTA +
1098 RG_SCH_CMN_HARQ_INTERVAL ) % RG_MAX_NUM_DLSF;*/
1100 /* Must get the DLSF that is scheduled at TFU_DELTA Away */
1102 if(cell->ulDlCfgIdx == 5)
1106 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DELTA);
1107 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
1108 RG_SCH_TDD_DL_SUBFRAME)
1113 /* Introduced timing delta for DL control in FDD */
1114 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DLCNTRL_DLDELTA);
1116 dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
1117 queue = &(dlSf->ueLst);
1119 node = queue->first;
1122 ue = (RgSchUeCb *)(node->node);
1124 hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
1127 hqP = (RgSchDlHqProcCb *)hqNode->node;
1128 hqNode = hqNode->next;
1129 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1131 tbCb = &hqP->tbInfo[i];
1132 if (tbCb->fbkRepCntr > 0)
1134 ue->ul.ulInactvMask |= RG_ACKNAKREP_INACTIVE;
1135 /* Check if already added to the list */
1136 if (!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1138 /* Add to the inactv list */
1139 ue->ul.ulInactvLnk.node = (PTR)ue;
1140 cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1144 repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime,
1145 ue->ackNakRepCb.repCntr);
1146 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK, repCntr);
1148 rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK,
1149 (ue->ackNakRepCb.repCntr));
1159 * @brief Handles processing of DL Inactive timer expiry at the end of
1160 * measurement gap or ack nack repetition for a UE
1164 * Function : rgSCHMeasGapANRepDlInactvTmrExpry
1166 * Invoking Module Processing:
1167 * - This API shall be invoked to process DL inactive timer expiry
1170 * - If timer event is RG_MEASGAP_DLINACTV,
1171 * - dlInactvMask &= ~RG_MEASGAP_INACTIVE
1172 * - If timer event is RG_ACKNAKREP_DLINACTV,
1173 * - dlInactvMask &= ~RG_ACKNAKREP_INACTIVE
1174 * - if (!dlInactvMask)
1175 * - Invoke DL scheduler to put the UE back into the scheduling queues.
1176 * - Re-initialize timer.
1179 * @param[in] RgSchUeCb *ue
1180 * @param[in] Check if some timer related parameter needs to be passed
1186 Void rgSCHMeasGapANRepDlInactvTmrExpry
1192 Void rgSCHMeasGapANRepDlInactvTmrExpry(ue, tmrEvnt)
1198 RgSchCellCb *cell = ue->cell;
1202 case RG_SCH_TMR_DL_MEASGAP:
1203 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1205 case RG_SCH_TMR_DL_ACKNACK:
1206 RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1209 if (!ue->dl.dlInactvMask)
1211 cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
1212 cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
1218 * @brief Handles processing of UL Inactive timer expiry at the end of
1219 * measurement gap or ack nack repetition for a UE
1223 * Function : rgSCHMeasGapANRepUlInactvTmrExpry
1225 * Invoking Module Processing:
1226 * - This API shall be invoked to process UL inactive timer expiry
1229 * - If timer event is RG_MEASGAP_ULINACTV,
1230 * - ulInactvMask &= ~RG_MEASGAP_INACTIVE
1231 * - If timer event is RG_ACKNAKREP_ULINACTV,
1232 * - ulInactvMask &= ~RG_ACKNAKREP_INACTIVE
1233 * - if (!ulInactvMask)
1234 * - Invoke UL scheduler to put the UE back into the scheduling queues.
1235 * - Re-initialize timer.
1238 * @param[in] RgSchUeCb *ue
1239 * @param[in] Check if some timer related parameter needs to be passed
1245 Void rgSCHMeasGapANRepUlInactvTmrExpry
1251 Void rgSCHMeasGapANRepUlInactvTmrExpry(ue, tmrEvnt)
1256 RgSchCellCb *cell = ue->cell;
1260 case RG_SCH_TMR_UL_MEASGAP:
1261 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1263 case RG_SCH_TMR_UL_ACKNACK:
1264 RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1267 if (!ue->ul.ulInactvMask)
1269 cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
1270 cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
1276 * @brief Handles processing of measurement gap timer expiry at the end of
1281 * Function : rgSCHMeasGapANRepTmrExpry
1283 * Invoking Module Processing:
1284 * - This API shall be invoked to process measurement gap timer expiry
1287 * - Set ue->isMeasuring = FALSE
1288 * - Re-initialize timer.
1291 * @param[in] RgSchUeCb *ue
1292 * @param[in] Check if some timer related parameter needs to be passed
1298 Void rgSCHMeasGapANRepTmrExpry
1303 Void rgSCHMeasGapANRepTmrExpry(ue)
1308 ue->measGapCb.isMeasuring = FALSE;
1309 cmInitTimers (&ue->measGapCb.measGapTmr, 1);
1315 * @brief Handles processing of ACK-NACK repetition timer expiry at the end of
1316 * ACK-NACK repetition.
1320 * Function : rgSchAckNakRepTmrExpry
1322 * Invoking Module Processing:
1323 * - This API shall be invoked to process ACK-NACK repetition timer expiry
1326 * - Set ue->isAckNakRep = FALSE
1327 * - Re-initialize timer.
1330 * @param[in] RgSchUeCb *ue
1331 * @param[in] Check if some timer related parameter needs to be passed
1337 Void rgSCHAckNakRepTmrExpry
1342 Void rgSCHAckNakRepTmrExpry(ue)
1347 ue->ackNakRepCb.isAckNakRep = FALSE;
1348 cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
1355 * @brief Adds ACK-NACK repeating UEs to the ackNakRepQ
1359 * Function : rgSchAckNakRepAddToQ
1361 * Invoking Module Processing:
1362 * - This API shall be invoked for adding list of UEs to the ACK-NACK
1363 * repeating queue at appropriate poistion. Invoking module shall invoke
1364 * with the list of ACK-NACK repeating UEs for a sub-frame and timing info
1365 * at which ACK NACK repetition shall start for the UEs.
1368 * - Determine the qOffset depending on the timing info as
1369 * - qOffset = (repStartTime->sfn *10 + repStartTime->subframe) % RG_MAX_NUM_DLSF
1370 * - Initialize the list at the qOffset.
1371 * - For each UE in the list,
1372 * - Add the UE to ackNakRepQ to the list at the determined qOffset.
1373 * - Set ue->qOffset = qOffset
1374 * - Initialize timers.
1377 * @param[in] RgSchCellCb *cell
1378 * @param[in] RgSchDlSf *crntDlSf
1379 * @param[in] CmLteTimingInfo repStartTime
1386 Void rgSCHAckNakRepAddToQ
1392 Void rgSCHAckNakRepAddToQ(cell, crntDlSf)
1394 RgSchDlSf *crntDlSf;
1400 RgSchDlHqProcCb *hqP;
1401 RgSchDlHqTbCb *tbCb;
1404 node = crntDlSf->ueLst.first;
1407 ue = (RgSchUeCb *)(node->node);
1409 hqNode = ue->dl.dlSfHqInfo[cell->cellId][crntDlSf->dlIdx].hqPLst.first;
1412 hqP = (RgSchDlHqProcCb *)hqNode->node;
1413 hqNode = hqNode->next;
1414 for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1416 tbCb = &hqP->tbInfo[i];
1417 /* Add UEs that have enabled ACK NACK repetition */
1418 if (ue->ackNakRepCb.isAckNackEnabled)
1420 tbCb->fbkRepCntr = ue->ackNakRepCb.cfgRepCnt;
1421 tbCb->fbkRecpRepCntr = ue->ackNakRepCb.cfgRepCnt;
1422 /* Removed init of timers as the init will be happening during
1423 * config or timer expiry*/
1434 * @brief Finds the number of subframes used for ACK-NACK cycle
1438 * Function : rgSCHAckNakRepFindUlDuration
1440 * This function finds the number of subframes required
1441 * for ACK-NACK repetition cycle based on UL subframes.
1443 * @param[in] RgSchCellCb *cell
1444 * @param[in] RgSchDlSf *dlSf
1445 * @param[in] CmLteTimingInfo repTime
1446 * @param[in] uint8_t repCnt
1453 static uint8_t rgSCHAckNakRepFindUlDuration
1457 CmLteTimingInfo repTime,
1461 static uint8_t rgSCHAckNakRepFindUlDuration(cell, dlSf, repTime, repCnt)
1464 CmLteTimingInfo repTime;
1468 CmLteTimingInfo ulfrm;
1469 uint8_t noSubfrms = 0;
1470 uint16_t ulDlCfgIdx = cell->ulDlCfgIdx;
1475 rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, repTime, &noSubfrms);
1476 RG_SCH_ADD_TO_CRNT_TIME(repTime, ulfrm, noSubfrms);
1478 idx = ulfrm.subframe;
1481 idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
1482 if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] ==
1483 RG_SCH_TDD_UL_SUBFRAME)
1495 * @brief Finds the number of subframes used for ACK-NACK cycle
1499 * Function : rgSCHAckNakRepGetUlOffsetFrmDl
1501 * This function finds the number of subframes after
1502 * which UL subframes are present for the gicen DL
1505 * @param[in] RgSchDlSf *dlSf
1506 * @param[in] CmLteTimingInfo crntDlTime
1507 * @param[in] uint8_t *noSubfrms
1514 static Void rgSCHAckNakRepGetUlOffsetFrmDl
1517 CmLteTimingInfo crntDlTime,
1521 static Void rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, crntDlTime, noSubfrms)
1523 CmLteTimingInfo crntDlTime;
1528 if(dlSf->dlFdbkInfo.sfnOffset != 0)
1530 *noSubfrms = (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES;
1531 *noSubfrms = *noSubfrms + RGSCH_NUM_SUB_FRAMES - crntDlTime.subframe;
1532 *noSubfrms = *noSubfrms + dlSf->dlFdbkInfo.subframe;
1536 *noSubfrms = dlSf->dlFdbkInfo.subframe - crntDlTime.subframe;
1542 /**********************************************************************
1545 **********************************************************************/