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