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