Merge "Removed ANSI from multiple folder Part - 1 [JIRA ID - ODUHIGH-249]"
[o-du/l2.git] / src / 5gnrsch / rg_sch_mga.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     LTE-MAC layer
22  
23      Type:     C source file
24  
25      Desc:     C source code for Scheduler common functions
26  
27      File:     rg_sch_mga.c
28  
29 **********************************************************************/
30
31 /** @file rg_sch_mga.c
32 @brief This module handles schedulers' measurement gap and ack-nack repetiton functionality */
33
34 static const char* RLOG_MODULE_NAME="MAC";
35 static int RLOG_MODULE_ID=4096;
36 static int RLOG_FILE_ID=169;
37
38 /* header include files -- defines (.h) */
39 #include "common_def.h"
40 #include "lrg.h"
41 #include "rgr.h"
42 #include "tfu.h"
43 #include "rg_env.h"
44 #include "rg_sch_inf.h"
45 #include "rg_sch_err.h"
46 #include "rg_sch.h"
47 #include "rg_sch_cmn.h"
48 #include "rl_interface.h"
49 #include "rl_common.h"
50
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 */
57
58 /* local defines */
59 static S16 rgSCHMeasGapANRepUtlAddUe ARGS((
60 RgSchCellCb       *cell,
61 RgSchUeCb          *ue,
62 RgrUeMeasGapCfg    *cfg));
63
64 static S16 rgSCHMeasGapANRepUtlRmvUe ARGS((
65 RgSchCellCb       *cell,
66 RgSchUeCb          *ue));
67
68 static S16 rgSchAckNackRepUtlRmvUe ARGS((
69  RgSchCellCb      *cell,
70  RgSchUeCb        *ue));
71
72 static Void rgSchAckNackRepUtlHdlTti ARGS((
73 RgSchCellCb *cell,
74 CmLListCp   *ackNackRepQ));
75
76 static Void rgSCHMeasGapANRepUtlHdlTti ARGS((
77 RgSchCellCb *cell,
78 CmLListCp   *measGapQ));
79 #ifdef LTE_TDD
80 static uint8_t rgSCHAckNakRepFindUlDuration ARGS((
81 RgSchCellCb       *cell,
82 RgSchDlSf         *dlSf,
83 CmLteTimingInfo   repTime,
84 uint8_t                repCnt));
85 static Void rgSCHAckNakRepGetUlOffsetFrmDl ARGS((
86 RgSchDlSf         *dlSf,
87 CmLteTimingInfo   crntDlTime,
88 uint8_t                *noSubfrms));
89 #endif
90
91 /**
92  * @brief Handles Measurement gap and ack-nack repetition related 
93  * configuration for a UE.
94  *
95  * @details
96  *
97  *     Function : rgSCHMeasGapANRepUeCfg
98  *
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.
102  *        
103  *     Processing Steps:
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.
111  *      - else
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
117  *     - Return ROK
118  *
119  *  @param[in]  RgSchCellCb  *cell
120  *  @param[in]  RgSchUeCb    *ue
121  *  @param[in]  RgrUeCfg     *ueCfg
122  *
123  *  @return  S16
124  *      -# ROK
125  **/
126
127 S16 rgSCHMeasGapANRepUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg)
128 {
129
130    ue->measGapCb.isMesGapEnabled = ueCfg->ueMesGapCfg.isMesGapEnabled;
131
132    if (ueCfg->ueMesGapCfg.isMesGapEnabled)
133    {
134       ue->measGapCb.gapPrd          = ueCfg->ueMesGapCfg.gapPrd;
135       ue->measGapCb.gapOffst        = ueCfg->ueMesGapCfg.gapOffst;
136       rgSCHMeasGapANRepUtlAddUe (cell, ue, &(ueCfg->ueMesGapCfg));
137       cmInitTimers (&ue->measGapCb.measGapTmr, 1);
138       cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
139       cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
140    }
141
142    /* ACK NACK repetition part */
143    if (ueCfg->ueAckNackCfg.isAckNackEnabled)
144    {
145       ue->ackNakRepCb.cfgRepCnt = ueCfg->ueAckNackCfg.ackNackRepFactor;
146       ue->ackNakRepCb.repCntr = ue->ackNakRepCb.cfgRepCnt;
147       ue->ackNakRepCb.isAckNackEnabled = TRUE;
148       ue->ackNakRepCb.pucchRes = ueCfg->ueAckNackCfg.pucchAckNackRep;
149       cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
150       cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
151       cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
152    }
153    return ROK;
154 }
155
156 /**
157  * @brief Handles Measurement gap and ack-nack repetition related 
158  * re-configuration for a UE.
159  *
160  * @details
161  *
162  *     Function : rgSCHMeasGapANRepUeRecfg
163  *
164  *     Invoking Module Processing:
165  *      - This shall be invoked by SCH_GOM at UE re-configuration. It shall do the
166  *        validations for the spec-defined values.
167  *        
168  *     Processing Steps:
169  *      - For measurement gap,
170  *       - If measurement gap period or offset is re-configured, remove UE from
171  *         the previous list, if any and add it to the new list.
172  *       - Update configured values appropriately.
173  *      - For ACK-NACK repetition,
174  *       - Update the configured value. Set 'cfgRepCnt' variable value.
175  *       - If (repCntr == 0)
176  *         - repCntr = cfgRepCnt.
177  *         - qOffst = RG_INVALID_ACKNACKREPQ_ID
178  *       
179  *  @param[in]  RgSchCellCb  *cell
180  *  @param[in]  RgSchUeCb    *ue
181  *  @param[in]  RgrUeRecfg   *ueRecfg
182  *
183  *  @return  S16
184  *      -# ROK
185  *      -# RFAILED
186  **/
187
188 S16 rgSCHMeasGapANRepUeRecfg(RgSchCellCb  *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg)
189 {
190    RgrUeMeasGapCfg         *reCfg;
191    RgSchUeMeasGapCb        *ueMeasCb;
192    RgrUeAckNackRepCfg      *ackNackReCfg = &(ueRecfg->ueAckNackRecfg);
193    RgSchUeAckNakRepCb      *ackNakRepCb = &(ue->ackNakRepCb);
194
195    reCfg    = &(ueRecfg->ueMeasGapRecfg);
196    ueMeasCb = &(ue->measGapCb);
197
198    /* Removed extra comments
199     * Check this once again Check to see if anything changed or not */
200    if ((reCfg->isMesGapEnabled == TRUE) &&
201          (ueMeasCb->isMesGapEnabled == TRUE) &&
202          (reCfg->gapPrd == ueMeasCb->gapPrd) &&
203          (reCfg->gapOffst == ueMeasCb->gapOffst))
204    {
205       /* Nothing changed hence nothing to do */
206    }
207    else
208    {
209       if (reCfg->isMesGapEnabled)
210       {
211          if (ueMeasCb->isMesGapEnabled)
212          {
213             rgSCHMeasGapANRepUtlRmvUe (cell, ue);
214          } 
215          else
216          {
217             cmInitTimers (&ueMeasCb->measGapTmr, 1);
218             cmInitTimers (&ueMeasCb->measGapUlInactvTmr, 1);
219             cmInitTimers (&ueMeasCb->measGapDlInactvTmr, 1);
220          } 
221
222          /* Add to the correct Measurement gap queue */
223          rgSCHMeasGapANRepUtlAddUe (cell, ue, reCfg);
224
225          ueMeasCb->gapPrd = reCfg->gapPrd;
226          ueMeasCb->gapOffst = reCfg->gapOffst;
227          ueMeasCb->isMesGapEnabled = TRUE;
228       } /* if new config has Measurement gap enabled */
229       else
230       {
231          if (ueMeasCb->isMesGapEnabled)
232          {
233             /* check if return value needed or not */
234             rgSCHMeasGapANRepUtlRmvUe (cell, ue);
235             ueMeasCb->isMesGapEnabled = FALSE;
236          } 
237       } /* if new config has Measurement gap disabled */
238    } /* For MeasGap configuration */
239
240    if (ackNackReCfg->isAckNackEnabled)
241    {
242       if (!ackNakRepCb->isAckNackEnabled)
243       {
244          ackNakRepCb->isAckNackEnabled = TRUE;
245          /* Timers need to be init immediately after config*/
246          cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
247          cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
248          cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
249       } /* repetition was disabled */
250       ackNakRepCb->pucchRes   = ackNackReCfg->pucchAckNackRep;
251       ackNakRepCb->cfgRepCnt  = ackNackReCfg->ackNackRepFactor;
252       if (ackNakRepCb->repCntr == 0)
253       {
254          ackNakRepCb->repCntr = ackNackReCfg->ackNackRepFactor;
255       }
256    } /* repetition enabled in re configuration */
257    else
258    {
259       ackNakRepCb->isAckNackEnabled = FALSE;
260    } /* repetition disabled in re configuration */
261
262    return ROK;
263 }
264
265  /** @brief This function is a utility to add the UE to the correct Measurement
266   * queue present in the cellCb.
267   *
268   * @details
269   *
270   *     Function: 
271   *
272   *         Processing steps:
273   *         - 
274   *
275   *
276   * @param  
277   * @param 
278   * @return 
279   */
280 static S16 rgSCHMeasGapANRepUtlAddUe(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeMeasGapCfg *cfg)
281 {
282
283    switch (cfg->gapPrd)
284    {
285       case RG_MEAS_GAPPRD_40:
286          /* Insert the UE into the linked list based on the gap Offset */
287          ue->measGapCb.measQLnk.node = (PTR)ue;
288          cmLListAdd2Tail (&(cell->measGapCb.gapPrd40Q[cfg->gapOffst]), 
289                &(ue->measGapCb.measQLnk));
290          break;
291       case RG_MEAS_GAPPRD_80:
292          ue->measGapCb.measQLnk.node = (PTR)ue;
293          cmLListAdd2Tail (&(cell->measGapCb.gapPrd80Q[cfg->gapOffst]), 
294                &(ue->measGapCb.measQLnk));
295          break;
296       default:
297          RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, 
298                   "rgSCHMeasGapANRepUeRecfg() Incorrect GAP Period"
299                   "CRNTI:%d",ue->ueId);
300          return RFAILED;
301    }
302    return ROK;
303 } /* end of rgSCHMeasGapANRepUtlAddUe */ 
304
305
306  /** @brief This function is a utility function to remove the ue from the measQ
307   * preset in tthe cell Cb.
308   *
309   * @details
310   *
311   *     Function: 
312   *
313   *         Processing steps:
314   *         - 
315   *
316   * @param  
317   * @param 
318   * @return 
319   */
320 static S16 rgSCHMeasGapANRepUtlRmvUe(RgSchCellCb *cell,RgSchUeCb *ue)
321 {
322
323    switch (ue->measGapCb.gapPrd)
324    {
325       case RG_MEAS_GAPPRD_40:
326          /* Remove from the existing list */
327          cmLListDelFrm (&(cell->measGapCb.gapPrd40Q[ue->measGapCb.gapOffst]), 
328                &(ue->measGapCb.measQLnk));
329          ue->measGapCb.measQLnk.node = NULLP;
330          break;
331       case RG_MEAS_GAPPRD_80:
332          /* Remove from the existing list */
333          cmLListDelFrm (&(cell->measGapCb.gapPrd80Q[ue->measGapCb.gapOffst]), 
334                &(ue->measGapCb.measQLnk));
335          ue->measGapCb.measQLnk.node = NULLP;
336          break;
337    }
338    return ROK;
339 } /* end of rgSCHMeasGapANRepUtlRmvUe */ 
340
341 /**
342  * @brief Frees Measurement gap and ack-nack repetition related data structures in UE
343  *
344  * @details
345  *
346  *     Function : rgSCHMeasGapANRepUeDel
347  *
348  *     Invoking Module Processing:
349  *      - This shall be invoked by SCH_GOM at Ue deletion.
350  *        
351  *     Processing Steps:
352  *      - For measurement gap, 
353  *       - if (measGapOffst != RG_INVALID_MEASGAPQ_ID)
354  *        - Remove from the measurement queue depending on the measGapPrd
355  *          value.
356  *        - Delete all timers
357  *      - For ACK-NACK repetition,
358  *       - if (qOffst != RG_INVALID_ACKNACKREPQ_ID)
359  *        - Remove from the ackNakRepQ queue  
360  *        - Delete all timers
361  *      - Return ROK
362  *
363  *  @param[in]  RgSchCellCb  *cell
364  *  @param[in]  RgSchUeCb    *ue
365  *
366  *  @return  S16
367  *      -# ROK
368  **/
369
370 Void rgSCHMeasGapANRepUeDel(RgSchCellCb *cell,RgSchUeCb *ue,Bool isUeDel)
371 {
372
373    if (ue->measGapCb.isMesGapEnabled)
374    {
375       rgSCHMeasGapANRepUtlRmvUe (cell, ue);
376       /* Must stop the timer if its running */
377       if (ue->measGapCb.isMeasuring)
378       {
379          rgSCHTmrStopTmr (cell, RG_SCH_TMR_MEASGAP, ue);
380       }
381
382       ue->measGapCb.isMesGapEnabled = FALSE;
383    }
384
385    /* Stop timers if running */
386    if (ue->dl.dlInactvMask)
387    {
388       if (ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE)
389       {
390          rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_MEASGAP, ue);
391       }
392       if (ue->dl.dlInactvMask & RG_ACKNAKREP_INACTIVE)
393       {
394          rgSCHTmrStopTmr (cell, RG_SCH_TMR_DL_ACKNACK, ue);
395       }
396       ue->dl.dlInactvLnk.node = NULLP;
397    }
398    if (ue->ul.ulInactvMask)
399    {
400       if (ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE)
401       {
402          rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_MEASGAP, ue);
403       }
404       if (ue->ul.ulInactvMask & RG_ACKNAKREP_INACTIVE)
405       {
406          rgSCHTmrStopTmr (cell, RG_SCH_TMR_UL_ACKNACK, ue);
407       }
408       ue->ul.ulInactvLnk.node = NULLP;
409    }
410
411    /* ccpu00133470- Releasing ACKNACK Rep UE Deleted */
412    if (isUeDel & ue->ackNakRepCb.isAckNakRep)
413    {
414       rgSCHTmrStopTmr (cell, RG_SCH_TMR_ACKNACK_REP, ue);
415       rgSchAckNackRepUtlRmvUe (cell, ue);
416    }
417    return;
418 }
419
420  /** @brief This function deletes the UEs information related to ACK NACK
421   * repetition.
422   *
423   * @details
424   *
425   *     Function: 
426   *
427   *         Processing steps:
428   *         - Mainly we need to remove the UEs hqProcs from the ackNackQ(s)
429   *         present in the subframes.
430   *
431   *
432   * @param  
433   * @param 
434   * @return 
435   */
436 static S16 rgSchAckNackRepUtlRmvUe(RgSchCellCb *cell,RgSchUeCb *ue)
437 {
438
439
440    uint8_t           hqIdx;
441    uint8_t           repIdx;
442    RgSchDlHqProcCb   *hqP;
443    uint8_t           tbCnt;
444
445    RgSchDlHqEnt      *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
446
447    for (hqIdx = 0; hqIdx < hqEnt->numHqPrcs; hqIdx++)
448    {
449       hqP = &hqEnt->procs[hqIdx];
450       /* Starting from index 1 as index 0 isn't used */
451       for (repIdx = 1; repIdx < ue->ackNakRepCb.cfgRepCnt; repIdx++)
452       {
453          for (tbCnt = 0; tbCnt < 2; tbCnt++)
454          {
455             if ((hqP->tbInfo[tbCnt].crntSubfrm[repIdx] != NULLP) &&
456                   (hqP->tbInfo[tbCnt].anRepLnk[repIdx].node != NULLP))
457             {
458                cmLListDelFrm(&((hqP->tbInfo[tbCnt].crntSubfrm[repIdx])->\
459                ackNakRepQ), &hqP->tbInfo[tbCnt].anRepLnk[repIdx]);
460                hqP->tbInfo[tbCnt].anRepLnk[repIdx].node = NULLP;
461                hqP->tbInfo[tbCnt].crntSubfrm[repIdx] = NULLP;
462             }
463          }
464       }
465    }
466  
467    return ROK;
468 } /* end of */ 
469
470
471 /**
472  * @brief Per TTI processing for measurement gap and ack nack repetition
473  * handling.
474  *
475  * @details
476  *
477  *     Function : rgSCHMeasGapANRepTtiHndl
478  *
479  *     Invoking Module Processing:
480  *     - This shall be invoked by SCH_TOM on recieving TTI indication from PHY
481  *     . SCH_TOM shall update the cell->crntTime before invoking this API.     
482  *        
483  *     Processing Steps:
484  *     - Compute qOffset for 40ms queue as = 
485  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_40.
486  *       - Mark all the UEs at computed offset for performing measurement. Set
487  *         isMeasuring = TRUE.
488  *       - Start measGapTmr for each UE:
489  *          - length = RG_MEAS_GAP_LEN.
490  *          - event = RG_MEASGAP_ON
491  *          - handler = rgSCHMeasGapANRepTmrExpry
492  *       - Reinitalize the list at the offset.
493  *     - Compute qOffset for 80ms queue as = 
494  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MEAS_GAPPRD_80.
495  *       - Mark all the UEs at computed offset for performing measurement. Set
496  *         isMeasuring = TRUE.
497  *       - Start measGapTmr for each UE:
498  *          - length = RG_MEAS_GAP_LEN.
499  *          - event = RG_MEASGAP_ON
500  *          - handler = rgSCHMeasGapANRepTmrExpry
501  *       - Reinitalize the list at the offset.
502  *     - Compute qOffset for ACK NACK repetition queue as = 
503  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe)%RG_MAX_NUM_DLSF.
504  *       - Mark all the UEs at computed offset for performing ack-nack repetition. Set
505  *         isAckNakRep = TRUE.
506  *       - Start ackNakRepTmr for each UE: 
507  *          - length = repCntr.
508  *          - event = RG_ACKNAKREP_ON
509  *          - handler = rgSchAckNakRepTmrExpry
510  *       - Reinitalize the list at the offset.
511  *     - 'isMeasuring' bool value shall be cheked
512  *       - While sending dataRecpReq to PHY for non-adaptive uplink re-tx 
513  *         and if 'TRUE', no dataRecpReq shall be sent.
514  *       - While sending NACK as feedback to UE and if 'TRUE' no PHICH shall 
515  *         be sent and shall mark the UE for adaptive re-tx.
516  *       - While sending HqFbkRecpReq for a UE (applicable only if ACK NACK 
517  *         repetition coincides) and if 'TRUE',
518  *          - The request shall not be sent.
519  *          - Decrement repCntr
520  *          - if (repCntr == 0)
521  *            - Delete UE from the list.
522  *          - Move the Ue to next subframe's list of ACK-NACK repeating UEs.
523  *     - 'isAckNakRep' bool value shall be cheked
524  *       - While sending dataRecpReq to PHY for non-adaptive uplink re-tx 
525  *         and if 'TRUE', no dataRecpReq shall be sent.
526  *     - Check if any refresh for these cell-specific queues is needed
527  *     anywhere else as well.
528  *     - Check if TTI miss needs some trigger to the module.
529  *     - Return ROK
530  *
531  *  @param[in]  RgSchCellCb  *cell
532  *
533  *  @return  S16
534  *      -# ROK
535  **/
536
537 S16 rgSCHMeasGapANRepTtiHndl(RgSchCellCb *cell)
538 {
539    uint8_t          offset;
540    CmLListCp        *queue;
541    RgSchDlSf        *dlSf;
542    CmLteTimingInfo   repTime;
543
544    /* Measurement GAP Starts at offSet - however at MAC we are concerned at
545     * subframe + TFU_DELTA.
546     */
547    /* 40ms offset */
548    /* Introduced timing delta for DL control in FDD */
549 #ifdef LTE_TDD
550    offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) % 
551       RG_MEAS_GAPPRD_40;
552 #else
553    offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) % 
554       RG_MEAS_GAPPRD_40;
555 #endif
556    queue = &(cell->measGapCb.gapPrd40Q[offset]);
557    rgSCHMeasGapANRepUtlHdlTti (cell, queue);
558    /* 80ms offset */
559    /* Introduced timing delta for DL control in FDD */
560 #ifdef LTE_TDD
561    offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DELTA) % 
562       RG_MEAS_GAPPRD_80;
563 #else
564    offset = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + TFU_DLCNTRL_DLDELTA) % 
565       RG_MEAS_GAPPRD_80;
566 #endif
567    queue = &(cell->measGapCb.gapPrd80Q[offset]);
568    rgSCHMeasGapANRepUtlHdlTti (cell, queue);
569
570    /* for ACK NACK repetition starts at offset - however at MAC we are 
571     * concerned with subframe - TFU_DELTA */
572    /* offset = ((cell->crntTime.sfn * 10) + cell->crntTime.slot) % 
573     * RG_MAX_NUM_DLSF; */
574    /* We wish to get the subframe whose HARQ Reception request would go out in
575     * this subframe. HARQ_RTT - TFU_DELTA
576     */
577    /* Introduced timing delta for reception req */
578 #ifdef LTE_TDD
579    /* ACC_TDD */
580    //RGSCHSUBFRMCRNTTIME(cell->crntTime, repTime, (4 - TFU_DELTA));
581    RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA));
582 #else
583    RGSCHDECRFRMCRNTTIME(cell->crntTime, repTime, (RG_SCH_CMN_HARQ_INTERVAL - TFU_RECPREQ_DLDELTA)); 
584 #endif
585    dlSf = rgSCHUtlSubFrmGet (cell, repTime);
586    queue = &(dlSf->ueLst);
587    rgSchAckNackRepUtlHdlTti (cell, queue);
588
589    return ROK;
590 }
591
592  /** @brief This function Marks the UE as ackNakRep so that Reception request
593   * isnt sent for any other thing than HARQ.
594   *
595   * @details
596   *
597   *     Function: 
598   *
599   *         Processing steps:
600   *         - Loop through HARQ procs of the DlSf.
601   *         - If the UE is a repeating one 
602   *           - Mark as ackNakRep = TRUE
603   *           - Start the timer 
604   *
605   * @param  RgSchCellCb *cell
606   * @param  CmLListCp   *ackNakRepQ
607   * @return Void
608   */
609 static Void rgSchAckNackRepUtlHdlTti(RgSchCellCb *cell,CmLListCp   *ackNackRepQ)
610 {
611    CmLList           *node;
612    RgSchUeCb         *ue;
613
614    node = ackNackRepQ->first;
615    while (node)
616    {
617       ue = (RgSchUeCb *)(node->node);
618       if ((NULLP != ue) && (ue->ackNakRepCb.isAckNackEnabled))
619       {
620          ue->ackNakRepCb.isAckNakRep = TRUE;
621          rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_ACKNACK_REP, 
622                ue->ackNakRepCb.repCntr);
623       }
624       node = node->next;
625    } /* end of while */
626    return;
627 } /* end of */ 
628
629
630  /** @brief This function 
631   *
632   * @details
633   *
634   *     Function: 
635   *
636   *         Processing steps:
637   *         - 
638   *
639   *
640   * @param  
641   * @param 
642   * @return 
643   */
644 static Void rgSCHMeasGapANRepUtlHdlTti(RgSchCellCb *cell,CmLListCp   *measGapQ)
645 {
646    CmLList           *node;
647    RgSchUeCb         *ue;
648
649    node = measGapQ->first;
650    while (node)
651    {
652       ue    = (RgSchUeCb*)node->node;
653       ue->measGapCb.isMeasuring = TRUE;
654       rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_MEASGAP, RG_SCH_MEAS_GAP_LEN);
655       node = node->next;
656    } /* end of while */
657    return;
658 } /* end of */ 
659
660
661 /**
662  * @brief Determines the list of UEs inactive for DL scheduling due to
663  * measurement gap and ack nack repetitions
664  *
665  * @details
666  *
667  *     Function : rgSCHMeasGapANRepGetDlInactvUe
668  *
669  *     Invoking Module Processing:
670  *     - This API shall be invoked to get list of inactive UEs for downlink
671  *     scheduling due to measurement gaps and ACK NACK repetitions.
672  *        
673  *     Processing Steps:
674  *     - Compute qOffset for 40ms or 80ms queue as = 
675  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
676  *     RG_SCH_CMN_HARQ_INTERVAL)
677  *     % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
678  *       - Add all the UEs at computed offset to dlInactvUeLst since the
679  *         DL transmission or feedback transmission from UE for DL 
680  *         transmissions shall collide with measurement gap.
681  *       - Mark each UE. Set dlInactvMask |= RG_MEASGAP_INACTIVE
682  *       - Start measGapDlInactvTmr timer for each UE,
683  *         - length = RG_MEAS_GAP_LEN + RG_SCH_CMN_HARQ_INTERVAL
684  *         - event = RG_MEASGAP_DLINACTV
685  *         - handler = rgSCHMeasGapANRepDlInactvTmrExpry
686  *     - Compute qOffset for ACK NACK repetition queue as = 
687  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + DL_DELTA +
688  *     RG_SCH_CMN_HARQ_INTERVAL -1)
689  *     % RG_MAX_NUM_DLSF.
690  *       - Add all the UEs at computed offset to dlInactvUeLst since the
691  *         feedback transmission from UE for DL transmissions shall 
692  *         collide with ACK NACK repetition of the UE.
693  *       - Mark each UE. Set dlInactvMask |= RG_ACKNAKREP_INACTIVE
694  *       - Start ackNakRepDlInactvTmr timer for each UE,
695  *         - length = repCntr - 1
696  *         - event = RG_ACKNAKREP_DLINACTV
697  *         - handler = rgSCHMeasGapANRepDlInactvTmrExpry
698  *     - Verify the above computations before coding
699  *       
700  *     - Return ROK
701  *
702  *  @param[in]  RgSchCellCb  *cell
703  *  @param[out] CmLListCp    *dlInactvUeLst
704  *  @return  S16
705  *      -# ROK
706  **/
707 S16 rgSCHMeasGapANRepGetDlInactvUe(RgSchCellCb *cell,CmLListCp   *dlInactvUeLst)
708 {
709    uint8_t           offset;
710    CmLList           *node;
711    CmLList           *hqNode;
712    CmLListCp         *queue;
713    RgSchUeCb         *ue;
714    RgSchDlSf         *dlSf;
715    CmLteTimingInfo   ackNakTime;
716    uint16_t          schedTime;
717    uint8_t           harqFdbkOffset;
718 #ifdef LTE_TDD
719    uint8_t           repCntr;
720 #endif
721    RgSchDlHqProcCb   *hqP;
722    RgSchDlHqTbCb     *tbCb;
723    uint32_t          i;
724
725    schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + RG_DL_DELTA; 
726
727 #ifdef LTE_TDD
728    RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
729    if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
730          RG_SCH_TDD_DL_SUBFRAME)
731    {
732       return ROK;
733    }
734
735    dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
736    if(dlSf->dlFdbkInfo.sfnOffset > 0)
737    {
738       harqFdbkOffset =  
739          (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES+ \
740          RGSCH_NUM_SUB_FRAMES - ackNakTime.subframe + \
741          dlSf->dlFdbkInfo.subframe;
742    }
743    else
744    {
745       harqFdbkOffset =  dlSf->dlFdbkInfo.subframe - ackNakTime.subframe;
746    }
747 #else
748    harqFdbkOffset = RG_SCH_CMN_HARQ_INTERVAL;
749 #endif
750    /* Calc offset for Measurement gap 40 */
751    offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_40;
752    queue = &(cell->measGapCb.gapPrd40Q[offset]);
753
754    node = queue->first;
755    while (node)
756    {
757       ue = (RgSchUeCb*)node->node;
758       ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
759       /* Add to the inactv list */
760       ue->dl.dlInactvLnk.node = (PTR)ue;
761       cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
762       /* Start timer */
763       rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP, 
764             (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
765       node = node->next;
766    }
767
768    /* Calc offset for Measurement gap 80 */
769    offset = (schedTime + harqFdbkOffset) % RG_MEAS_GAPPRD_80;
770    queue = &(cell->measGapCb.gapPrd80Q[offset]);
771
772    node = queue->first;
773    while (node)
774    {
775       ue = (RgSchUeCb*)node->node;
776       ue->dl.dlInactvMask |= RG_MEASGAP_INACTIVE;
777       /* Add to the inactv list */
778       ue->dl.dlInactvLnk.node = (PTR)ue;
779       cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
780       /* Start timer */
781       rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_MEASGAP, 
782             (RG_SCH_MEAS_GAP_LEN + harqFdbkOffset));
783       node = node->next;
784    }
785
786    /* Calc offset for ACK NACK repetition */
787    /*offset = (cell->crntTime.sfn * 10 + 
788      cell->crntTime.slot + RG_DL_DELTA + RG_SCH_CMN_HARQ_INTERVAL - 1) 
789      % RG_MAX_NUM_DLSF;*/
790    /* The ackNakRepQ resides in each dlSf corresponding to the repStart */
791    /* Must pick up the subframe that was scheduled in the last TTI */
792 #ifdef LTE_TDD
793    if(cell->ulDlCfgIdx == 5)
794    {
795       return ROK;
796    }
797    rgSCHUtlGetPrevDlSfInfo(cell, ackNakTime, &ackNakTime, &repCntr);
798    dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
799    /* crnt DL subframe */
800    RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
801 #else
802    if(0 == RG_DL_DELTA)
803    {
804      /* Go to the subframe being scheduled */
805      RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, RG_DL_DELTA);
806      /* Go to the previous subframe */
807      RGSCHDECRFRMCRNTTIME(ackNakTime, ackNakTime, 1);
808    }
809    else
810    {
811      RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime,
812            (RG_DL_DELTA - 1));
813    }
814    dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
815 #endif
816    queue = &(dlSf->ueLst);
817
818    node = queue->first;
819    while (node)
820    {
821       ue = (RgSchUeCb *)(node->node);
822       node = node->next;
823       hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
824       while (hqNode)
825       {
826          hqP = (RgSchDlHqProcCb *)hqNode->node;
827          hqNode = hqNode->next;
828          for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
829          {
830             tbCb = &hqP->tbInfo[i];
831             if (tbCb->fbkRepCntr > 0)
832             {
833                ue->dl.dlInactvMask |= RG_ACKNAKREP_INACTIVE;
834                /* Check if already added to the list */
835                if (!(ue->dl.dlInactvMask & RG_MEASGAP_INACTIVE))
836                {
837                   /* Add to the inactv list */
838                   ue->dl.dlInactvLnk.node = (PTR)ue;
839                   cmLListAdd2Tail (dlInactvUeLst, &(ue->dl.dlInactvLnk));
840                }
841                /* Start timer */
842 #ifdef LTE_TDD
843                repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime, 
844                      (uint8_t)(ue->ackNakRepCb.repCntr - 1));
845                rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK, repCntr);
846 #else
847                rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_DL_ACKNACK, 
848                      (ue->ackNakRepCb.repCntr - 1));
849 #endif
850             }
851          }
852       }
853    }
854    return ROK;
855 }
856
857 /**
858  * @brief Determines the list of UEs inactive for UL scheduling due to
859  * measurement gap and ack nack repetitions
860  *
861  * @details
862  *
863  *     Function : rgSCHMeasGapANRepGetUlInactvUe
864  *
865  *     Invoking Module Processing:
866  *     - This API shall be invoked to get list of inactive UEs for uplink
867  *     scheduling due to measurement gaps and ACK NACK repetitions.
868  *        
869  *     Processing Steps:
870  *     - Compute qOffset for 40ms or 80ms queue as = 
871  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
872  *     RG_SCH_CMN_HARQ_INTERVAL)
873  *     % RG_MEAS_GAPPRD_40 or RG_MEAS_GAPPRD_80.
874  *       - Add all the UEs at computed offset to ulInactvUeLst since the UL
875  *         transmissions shall collide with measurement gap.
876  *       - Mark each UE. Set ulInactvMask |= RG_MEASGAP_INACTIVE
877  *       - Start measGapUlInactvTmr timer for each UE 
878  *         - length = RG_MEAS_GAP_LEN
879  *         - event = RG_MEASGAP_ULINACTV
880  *         - handler = rgSCHMeasGapANRepUlInactvTmrExpry
881  *     - Compute qOffset for ACK NACK repetition queue as = 
882  *     ((cell->crntTime->sfn * 10)+cell->crntTime->subframe + TFU_DELTA +
883  *     RG_SCH_CMN_HARQ_INTERVAL)
884  *     % RG_MAX_NUM_DLSF.
885  *       - Add all the UEs at computed offset to ulInactvUeLst since the
886  *         feedback transmission from UE for DL transmissions shall 
887  *         collide with repeating ACK ACK-NACKs.
888  *       - Mark each UE. Set ulInactvMask |= RG_ACKNAKREP_INACTIVE
889  *       - Start ackNakRepUlInactv timer for each UE
890  *         - length = repCntr
891  *         - event = RG_ACKNAKREP_ULINACTV
892  *         - handler = rgSCHMeasGapANRepUlInactvTmrExpry
893  *     - Verify the above computations before coding
894  *     - Return ROK
895  *
896  *  @param[in]  RgSchCellCb  *cell
897  *  @param[out] CmLListCp    *ulInactvUeLst
898  *  @return  S16
899  *      -# ROK
900  **/
901
902 S16 rgSCHMeasGapANRepGetUlInactvUe(RgSchCellCb *cell,CmLListCp   *ulInactvUeLst)
903 {
904
905    uint8_t         offset;
906    CmLList         *node;
907    CmLList         *hqNode;
908    CmLListCp       *queue;
909    RgSchUeCb       *ue;
910    CmLteTimingInfo ackNakTime;
911    RgSchDlSf       *dlSf;
912    uint16_t        schedTime;
913    uint8_t         pdcchToPuschGap;
914    uint8_t         idx=0;
915 #ifdef LTE_TDD
916    uint8_t         repCntr;
917 #endif
918    RgSchDlHqProcCb   *hqP;
919    RgSchDlHqTbCb     *tbCb;
920    uint32_t          i;
921
922    /*ccpu00139481- Meas Gap should be monitored in UL with TFU_ULCNTRL_DLDELTA*/
923    schedTime = cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G + cell->crntTime.slot + \
924                TFU_ULCNTRL_DLDELTA;
925 #ifndef LTE_TDD
926    pdcchToPuschGap = RGSCH_PDCCH_PUSCH_DELTA;
927 #else
928    RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_ULCNTRL_DLDELTA);
929    pdcchToPuschGap = rgSchTddPuschTxKTbl[cell->ulDlCfgIdx][ackNakTime.subframe];
930    for(idx=0; pdcchToPuschGap && (idx< (pdcchToPuschGap+RG_SCH_MEAS_GAP_LEN)) ; idx++)
931 #endif
932    {
933       /* Calc offset for Measurement gap 40 */
934       offset = (schedTime + pdcchToPuschGap -idx + RG_MEAS_GAPPRD_40) % RG_MEAS_GAPPRD_40;
935       queue = &(cell->measGapCb.gapPrd40Q[offset]);
936       node = queue->first;
937       while (node)
938       {
939          ue = (RgSchUeCb*)node->node;
940          if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
941          {
942          ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
943          /* Add to the inactv list */
944          ue->ul.ulInactvLnk.node = (PTR)ue;
945          cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
946          /* Start timer Note the timer is started for a value GAP_LEN +
947           * RG_SCH_CMN_HARQ_INTERVAL. The "4"
948           * is added because for UE to transmit, the PDCCH must be sent 4 subframes
949           * ahead - UE cant read PDCCH format0 if it is in measurement gap. */
950          rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP, 
951                (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
952    //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);
953          }
954          node = node->next;
955       }
956
957       /* Calc offset for Measurement gap 80 */
958       offset = (schedTime + pdcchToPuschGap - idx + RG_MEAS_GAPPRD_80) % RG_MEAS_GAPPRD_80;
959       queue = &(cell->measGapCb.gapPrd80Q[offset]);
960
961       node = queue->first;
962       while (node)
963       {
964          ue = (RgSchUeCb*)node->node;
965          if(!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
966          {
967          ue->ul.ulInactvMask |= RG_MEASGAP_INACTIVE;
968          /* Add to the inactv list */
969          ue->ul.ulInactvLnk.node = (PTR)ue;
970          cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
971          /* Start timer */
972          rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_MEASGAP, 
973                (RG_SCH_MEAS_GAP_LEN + pdcchToPuschGap - idx));
974    //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);
975          }
976          node = node->next;
977       }
978    }
979    /* Calc offset for ACK NACK repetition */
980    /*offset = (cell->crntTime.sfn * 10 + 
981      cell->crntTime.slot + RG_UL_SCHED_DELTA + 
982      RG_SCH_CMN_HARQ_INTERVAL ) % RG_MAX_NUM_DLSF;*/
983
984    /* Must get the DLSF that is scheduled at TFU_DELTA Away */
985 #ifdef LTE_TDD
986    if(cell->ulDlCfgIdx == 5)
987    {
988       return ROK;
989    }
990    RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DELTA);
991    if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][ackNakTime.subframe] !=
992          RG_SCH_TDD_DL_SUBFRAME)
993    {
994       return ROK;
995    }
996 #else
997    /* Introduced timing delta for DL control in FDD */
998    RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, ackNakTime, TFU_DLCNTRL_DLDELTA);
999 #endif
1000    dlSf = rgSCHUtlSubFrmGet (cell, ackNakTime);
1001    queue = &(dlSf->ueLst);
1002
1003    node = queue->first;
1004    while (node)
1005    {
1006       ue = (RgSchUeCb *)(node->node);
1007       node = node->next;
1008       hqNode = ue->dl.dlSfHqInfo[cell->cellId][dlSf->dlIdx].hqPLst.first;
1009       while (hqNode)
1010       {
1011          hqP = (RgSchDlHqProcCb *)hqNode->node;
1012          hqNode = hqNode->next;
1013          for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1014          {
1015             tbCb = &hqP->tbInfo[i];
1016             if (tbCb->fbkRepCntr > 0)
1017             {
1018                ue->ul.ulInactvMask |= RG_ACKNAKREP_INACTIVE;
1019                /* Check if already added to the list */
1020                if (!(ue->ul.ulInactvMask & RG_MEASGAP_INACTIVE))
1021                {
1022                   /* Add to the inactv list */
1023                   ue->ul.ulInactvLnk.node = (PTR)ue;
1024                   cmLListAdd2Tail (ulInactvUeLst, &(ue->ul.ulInactvLnk));
1025                }
1026                /* Start timer */
1027 #ifdef LTE_TDD
1028                repCntr = rgSCHAckNakRepFindUlDuration(cell, dlSf, ackNakTime, 
1029                      ue->ackNakRepCb.repCntr);
1030                rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK, repCntr);
1031 #else
1032                rgSCHTmrStartTmr (cell, ue, RG_SCH_TMR_UL_ACKNACK, 
1033                      (ue->ackNakRepCb.repCntr));
1034 #endif
1035             }
1036          }
1037       }
1038    }
1039    return ROK;
1040 }
1041
1042 /**
1043  * @brief Handles processing of DL Inactive timer expiry at the end of
1044  * measurement gap or ack nack repetition for a UE
1045  *
1046  * @details
1047  *
1048  *     Function : rgSCHMeasGapANRepDlInactvTmrExpry
1049  *
1050  *     Invoking Module Processing:
1051  *     - This API shall be invoked to process DL inactive timer expiry
1052  *        
1053  *     Processing Steps:
1054  *     - If timer event is RG_MEASGAP_DLINACTV,
1055  *       - dlInactvMask &= ~RG_MEASGAP_INACTIVE
1056  *     - If timer event is RG_ACKNAKREP_DLINACTV,
1057  *       - dlInactvMask &= ~RG_ACKNAKREP_INACTIVE
1058  *     - if (!dlInactvMask)
1059  *       - Invoke DL scheduler to put the UE back into the scheduling queues.
1060  *       - Re-initialize timer.
1061  *     - Return ROK
1062  *
1063  *  @param[in]  RgSchUeCb  *ue
1064  *  @param[in]  Check if some timer related parameter needs to be passed
1065  *  @return  S16
1066  *      -# ROK
1067  **/
1068
1069 Void rgSCHMeasGapANRepDlInactvTmrExpry(RgSchUeCb *ue,uint8_t tmrEvnt)
1070 {
1071
1072    RgSchCellCb    *cell = ue->cell;
1073
1074    switch (tmrEvnt)
1075    {
1076       case RG_SCH_TMR_DL_MEASGAP:
1077          RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1078          break;
1079       case RG_SCH_TMR_DL_ACKNACK:
1080          RG_SCH_CMN_DL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1081          break;
1082    }
1083    if (!ue->dl.dlInactvMask)
1084    {
1085       cmInitTimers (&ue->measGapCb.measGapDlInactvTmr, 1);
1086       cmInitTimers (&ue->ackNakRepCb.ackNakRepDlInactvTmr, 1);
1087    }
1088    return;
1089 }
1090
1091 /**
1092  * @brief Handles processing of UL Inactive timer expiry at the end of
1093  * measurement gap or ack nack repetition for a UE
1094  *
1095  * @details
1096  *
1097  *     Function : rgSCHMeasGapANRepUlInactvTmrExpry
1098  *
1099  *     Invoking Module Processing:
1100  *     - This API shall be invoked to process UL inactive timer expiry
1101  *        
1102  *     Processing Steps:
1103  *     - If timer event is RG_MEASGAP_ULINACTV,
1104  *       - ulInactvMask &= ~RG_MEASGAP_INACTIVE
1105  *     - If timer event is RG_ACKNAKREP_ULINACTV,
1106  *       - ulInactvMask &= ~RG_ACKNAKREP_INACTIVE
1107  *     - if (!ulInactvMask)
1108  *       - Invoke UL scheduler to put the UE back into the scheduling queues.
1109  *       - Re-initialize timer.
1110  *     - Return ROK
1111  *
1112  *  @param[in]  RgSchUeCb  *ue
1113  *  @param[in]  Check if some timer related parameter needs to be passed
1114  *  @return  S16
1115  *      -# ROK
1116  **/
1117
1118 Void rgSCHMeasGapANRepUlInactvTmrExpry(RgSchUeCb *ue,uint8_t tmrEvnt)
1119 {
1120    RgSchCellCb       *cell = ue->cell;
1121
1122    switch (tmrEvnt)
1123    {
1124       case RG_SCH_TMR_UL_MEASGAP:
1125          RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_MEASGAP_INACTIVE);
1126          break;
1127       case RG_SCH_TMR_UL_ACKNACK:
1128          RG_SCH_CMN_UL_UPDT_INACTV_MASK ( cell, ue, RG_ACKNAKREP_INACTIVE);
1129          break;
1130    }
1131    if (!ue->ul.ulInactvMask)
1132    {
1133       cmInitTimers (&ue->measGapCb.measGapUlInactvTmr, 1);
1134       cmInitTimers (&ue->ackNakRepCb.ackNakRepUlInactvTmr, 1);
1135    }
1136    return;
1137 }
1138
1139 /**
1140  * @brief Handles processing of measurement gap timer expiry at the end of
1141  * measurement gap
1142  *
1143  * @details
1144  *
1145  *     Function : rgSCHMeasGapANRepTmrExpry
1146  *
1147  *     Invoking Module Processing:
1148  *     - This API shall be invoked to process measurement gap timer expiry
1149  *        
1150  *     Processing Steps:
1151  *     - Set ue->isMeasuring = FALSE
1152  *     - Re-initialize timer.
1153  *     - Return ROK
1154  *
1155  *  @param[in]  RgSchUeCb  *ue
1156  *  @param[in]  Check if some timer related parameter needs to be passed
1157  *  @return  S16
1158  *      -# ROK
1159  **/
1160
1161 Void rgSCHMeasGapANRepTmrExpry(RgSchUeCb *ue)
1162 {
1163
1164    ue->measGapCb.isMeasuring = FALSE;
1165    cmInitTimers (&ue->measGapCb.measGapTmr, 1);
1166
1167    return;
1168 }
1169
1170 /**
1171  * @brief Handles processing of ACK-NACK repetition timer expiry at the end of
1172  * ACK-NACK repetition.
1173  *
1174  * @details
1175  *
1176  *     Function : rgSchAckNakRepTmrExpry
1177  *
1178  *     Invoking Module Processing:
1179  *     - This API shall be invoked to process ACK-NACK repetition timer expiry
1180  *        
1181  *     Processing Steps:
1182  *     - Set ue->isAckNakRep = FALSE
1183  *     - Re-initialize timer.
1184  *     - Return ROK
1185  *
1186  *  @param[in]  RgSchUeCb  *ue
1187  *  @param[in]  Check if some timer related parameter needs to be passed
1188  *  @return  S16
1189  *      -# ROK
1190  **/
1191
1192 Void rgSCHAckNakRepTmrExpry(RgSchUeCb *ue)
1193 {
1194
1195    ue->ackNakRepCb.isAckNakRep = FALSE;
1196    cmInitTimers (&ue->ackNakRepCb.ackNakRepTmr, 1);
1197
1198    return; 
1199 }
1200
1201
1202 /**
1203  * @brief Adds ACK-NACK repeating UEs to the ackNakRepQ
1204  *
1205  * @details
1206  *
1207  *     Function : rgSchAckNakRepAddToQ
1208  *
1209  *     Invoking Module Processing:
1210  *     - This API shall be invoked for adding list of UEs to the ACK-NACK
1211  *     repeating queue at appropriate poistion. Invoking module shall invoke
1212  *     with the list of ACK-NACK repeating UEs for a sub-frame and timing info
1213  *     at which ACK NACK repetition shall start for the UEs.
1214  *        
1215  *     Processing Steps:
1216  *     - Determine the qOffset depending on the timing info as
1217  *       - qOffset = (repStartTime->sfn *10 + repStartTime->subframe) % RG_MAX_NUM_DLSF
1218  *     - Initialize the list at the qOffset. 
1219  *     - For each UE in the list,
1220  *       - Add the UE to ackNakRepQ to the list at the determined qOffset.
1221  *       - Set ue->qOffset = qOffset
1222  *       - Initialize timers.
1223  *     - Return ROK
1224  *
1225  *  @param[in]  RgSchCellCb  *cell
1226  *  @param[in]  RgSchDlSf    *crntDlSf
1227  *  @param[in]  CmLteTimingInfo repStartTime
1228  *
1229  *  @return  S16
1230  *      -# ROK
1231  **/
1232
1233 Void rgSCHAckNakRepAddToQ(RgSchCellCb       *cell,RgSchDlSf         *crntDlSf)
1234 {
1235    RgSchUeCb         *ue;
1236    CmLList           *node;
1237    CmLList           *hqNode;
1238    RgSchDlHqProcCb   *hqP;
1239    RgSchDlHqTbCb     *tbCb;
1240    uint32_t               i;
1241
1242    node = crntDlSf->ueLst.first;
1243    while (node)
1244    {
1245       ue = (RgSchUeCb *)(node->node);
1246       node = node->next;
1247       hqNode = ue->dl.dlSfHqInfo[cell->cellId][crntDlSf->dlIdx].hqPLst.first;
1248       while (hqNode)
1249       {
1250          hqP = (RgSchDlHqProcCb *)hqNode->node;
1251          hqNode = hqNode->next;
1252          for (i = 0;(i<2) && (hqP->tbInfo[i].state == HQ_TB_WAITING);i++)
1253          {
1254             tbCb = &hqP->tbInfo[i];
1255             /* Add UEs that have enabled ACK NACK repetition */
1256             if (ue->ackNakRepCb.isAckNackEnabled)
1257             {
1258                tbCb->fbkRepCntr = ue->ackNakRepCb.cfgRepCnt;
1259                tbCb->fbkRecpRepCntr = ue->ackNakRepCb.cfgRepCnt;
1260                /* Removed init of timers as the init will be happening during
1261                 * config or timer expiry*/
1262             }
1263          }
1264       }
1265    }
1266    return;
1267 }
1268
1269
1270 #ifdef LTE_TDD
1271 /**
1272  * @brief Finds the number of subframes used for ACK-NACK cycle
1273  *
1274  * @details
1275  *
1276  *     Function : rgSCHAckNakRepFindUlDuration
1277  *
1278  *                This function finds the number of subframes required
1279  *                for ACK-NACK repetition cycle based on UL subframes.
1280  *
1281  *  @param[in]  RgSchCellCb  *cell
1282  *  @param[in]  RgSchDlSf        *dlSf
1283  *  @param[in]  CmLteTimingInfo  repTime
1284  *  @param[in]  uint8_t           repCnt
1285  *
1286  *  @return  uint8_t
1287  *      
1288  **/
1289
1290 static uint8_t rgSCHAckNakRepFindUlDuration(RgSchCellCb *cell,RgSchDlSf *dlSf,CmLteTimingInfo repTime,uint8_t repCnt)
1291 {
1292    CmLteTimingInfo   ulfrm;
1293    uint8_t    noSubfrms = 0;
1294    uint16_t   ulDlCfgIdx = cell->ulDlCfgIdx;
1295    S16   rem = 0;
1296    S16   idx;
1297    S8    diff;
1298
1299    rgSCHAckNakRepGetUlOffsetFrmDl(dlSf, repTime, &noSubfrms);
1300    RG_SCH_ADD_TO_CRNT_TIME(repTime, ulfrm, noSubfrms);
1301    diff = repCnt-1;
1302    idx = ulfrm.subframe;
1303    while(diff)
1304       {
1305       idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
1306          if(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][idx] ==
1307                                     RG_SCH_TDD_UL_SUBFRAME)
1308          {
1309             diff--;
1310          }
1311       rem++;
1312       }
1313    noSubfrms += rem;
1314
1315    return (noSubfrms);
1316    }
1317
1318 /**
1319  * @brief Finds the number of subframes used for ACK-NACK cycle
1320  *
1321  * @details
1322  *
1323  *     Function : rgSCHAckNakRepGetUlOffsetFrmDl
1324  *
1325  *                This function finds the number of subframes after
1326  *                which UL subframes are present for the gicen DL
1327  *                subframe.
1328  *
1329  *  @param[in]  RgSchDlSf        *dlSf
1330  *  @param[in]  CmLteTimingInfo  crntDlTime
1331  *  @param[in]  uint8_t               *noSubfrms
1332  *
1333  *  @return  uint8_t
1334  *      
1335  **/
1336
1337 static Void rgSCHAckNakRepGetUlOffsetFrmDl(RgSchDlSf *dlSf,CmLteTimingInfo crntDlTime,uint8_t *noSubfrms )
1338 {
1339
1340    if(dlSf->dlFdbkInfo.sfnOffset != 0)
1341             {
1342       *noSubfrms = (dlSf->dlFdbkInfo.sfnOffset - 1) * RGSCH_NUM_SUB_FRAMES;
1343       *noSubfrms = *noSubfrms + RGSCH_NUM_SUB_FRAMES - crntDlTime.subframe;
1344       *noSubfrms = *noSubfrms + dlSf->dlFdbkInfo.subframe;
1345       }
1346    else
1347    {
1348       *noSubfrms = dlSf->dlFdbkInfo.subframe - crntDlTime.subframe;
1349    }
1350    return;
1351 }
1352 #endif
1353 \f
1354 /**********************************************************************
1355  
1356          End of file
1357 **********************************************************************/