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