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