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