fd58f6a9412a25bd09374fc5318e9341c6ace6c5
[o-du/l2.git] / src / 5gnrsch / rg_sch_pwr.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 power control functionality
26  
27      File:     rg_sch_pwr.c
28  
29 **********************************************************************/
30
31 /** @file rg_sch_pwr.c
32 @brief This module handles schedulers' power control functionality
33 */
34
35 /* header include files -- defines (.h) */
36 #include "common_def.h"
37 #include "lrg.h"
38 #include "rgr.h"
39 #include "rgm.h"
40 #include "tfu.h"
41 #include "rg_env.h"
42 #include "rg_sch_inf.h"
43 #include "rg_sch_err.h"
44 #include "rg_sch.h"
45 #include "rg_sch_cmn.h"
46
47 /* header/extern include files (.x) */
48 #include "tfu.x"           /* RGU types */
49 #include "lrg.x"           /* layer management typedefs for MAC */
50 #include "rgr.x"           /* layer management typedefs for MAC */
51 #include "rgm.x"           /* layer management typedefs for MAC */
52 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
53 #include "rg_sch.x"        /* typedefs for Scheduler */
54 #include "rg_sch_cmn.x"
55 #include "rl_interface.h"
56 #include "rl_common.h"
57
58
59 /* Current specs have 23 dBm as max tx power capability for UEs */
60 #define RG_SCH_PWR_UE_MAX_PWR    23
61
62 #define RG_SCH_REF_PCMAX         0xFF
63
64 #define RG_SCH_CMN_GET_UL_UE(_ue,_cell) (&(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
65                [RG_SCH_CELLINDEX(_cell)]])->sch))->ul))
66 #define RG_SCH_PWR_GETUEPWR(_ue, _cell) &(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
67                [RG_SCH_CELLINDEX(_cell)]])->sch))->ul.ulPwrCb)
68 #define RG_SCH_PWR_GETCELLPWR(cell) &((RgSchCmnCell *)((cell)->sc.sch))->ul.ulPwrCb
69
70
71 typedef S8 RgSchCmnUlPwrCqiToPwrTbl[RG_SCH_CMN_UL_NUM_CQI];
72
73 static RgSchCmnUlPwrCqiToPwrTbl rgSchPwrCqiToPwrTbl;
74
75 /* This table maps a given number of RBs (given by array index)
76  * to the power in dB that these many RBs map to. */
77 const uint8_t rgSchPwrRbToPwrTbl[111] = { 0,    /* First entry is dummy */
78    0,  3,  4,  6,  7,  7,  8,  9,  9,  10,
79    10, 10, 11, 11, 11, 12, 12, 12, 12, 13,
80    13, 13, 13, 13, 14, 14, 14, 14, 14, 14,
81    15, 15, 15, 15, 15, 15, 15, 15, 16, 16,
82    16, 16, 16, 16, 16, 16, 16, 16, 17, 17,
83    17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
84    17, 18, 18, 18, 18, 18, 18, 18, 18, 18,
85    18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
86    19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
87    19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
88    20, 20, 20, 20, 20, 20, 20, 20, 20, 20
89 };
90
91
92 /* This table maps power (in dB) to number of RBs */
93 /* The array size comes from max power in rgSchPwrRbToPwrTbl */
94 const uint8_t rgSchPwrToRbTbl[20+1] = {
95   1, 1, 2, 2, 3, 4, 5, 6, 7, 9, 11,
96   13, 17, 21, 26, 33, 41, 52, 65, 82, 103 
97 };
98
99
100
101 static S8 rgSCHPwrGetCqiPwr ARGS((
102          uint8_t                  cqi
103          ));
104 static S8 rgSCHPwrGetCqiPwrForUe ARGS((
105          RgSchCellCb          *cell,
106          RgSchUeCb          *ue,
107          uint8_t                  cqi
108          ));
109 static S8 rgSCHPwrCalcEfficncyPwr ARGS((
110          uint32_t                 eff
111          ));
112 static S8 rgSCHPwrGetDelta2FrmCqi ARGS((
113          uint8_t                  crntCqi,
114          uint8_t                  trgCqi,
115          RgSchUeCb           *ue,
116          RgSchCellCb         *cell
117          ));
118 static Void rgSCHPwrGetPuschTpc ARGS((
119          uint8_t                  isAcc,
120          S8                  delta,
121          S8                  availPwr,
122          uint8_t                 *tpc,
123          S8                 *tpcDelta
124          ));
125 static uint8_t rgSCHPwrGetMaxRb ARGS((
126          RgSchCellCb          *cell,
127          S8                  pwr
128          ));
129 static uint8_t rgSCHPwrRbToPwr ARGS((
130          RgSchCellCb          *cell,
131          uint8_t                  numRb
132          ));
133 static Void rgSCHPwrSchedPucchRnti ARGS((
134          RgSchCellCb          *cell,
135          RgSchCmnTpcRntiCb    *cb,
136          RgSchPdcch           *pdcch,
137          RgSchDlSf            *dlSf,
138          Bool                 *sched
139          ));
140 static Void rgSCHPwrPuschCntrl ARGS((
141          RgSchCellCb          *cell,
142          RgSchUeCb            *ue
143          ));
144 static Void rgSCHPwrPucchCntrl ARGS((
145          RgSchCellCb *cell,
146          RgSchUeCb   *ue
147          ));
148 static Void rgSCHPwrSchedPuschRnti ARGS((
149          RgSchCellCb          *cell,
150          RgSchCmnTpcRntiCb    *cb,
151          RgSchPdcch           *pdcch,
152          RgSchUlSf            *ulSf,
153          Bool                 *sched
154          ));
155 static Void rgSCHPwrGetPucchFmt3TpcForUe ARGS((
156          RgSchUeCb            *ue,
157          uint8_t                   *tpc,
158          S8                   *delta
159          ));
160 static Void rgSCHPwrGetPucchFmt3aTpcForUe ARGS((
161          RgSchUeCb            *ue,
162          uint8_t                   *tpc,
163          S8                   *delta
164          ));
165 static Void rgSCHPwrGetPuschFmt3TpcForUe ARGS((
166          RgSchUeCb            *ue,
167          uint8_t                   *tpc,
168          S8                   *delta
169          ));
170 static Void rgSCHPwrGetPuschFmt3aTpcForUe ARGS((
171          RgSchUeCb            *ue,
172          uint8_t                   *tpc,
173          S8                   *delta
174          ));
175 static Void rgSCHPwrGetAcc1bitTpc ARGS((
176          S8                    remPwr,
177          uint8_t                   *tpc,
178          S8                   *delta
179          ));
180 static Void rgSCHPwrGetAcc2bitTpc ARGS((
181          S8                   remPwr,
182          uint8_t                  *tpc,
183          S8                  *delta
184          ));
185 static Void rgSCHPwrGetAbsTpc ARGS((
186          S8                   remPwr,
187          uint8_t                  *tpc,
188          S8                  *delta
189          ));
190 static Void rgSCHPwrOnPucchGrpPwrForUe  ARGS((
191          RgSchCellCb          *cell,
192          RgSchUeCb            *ue,
193          S8                    delta
194          ));
195 static Void rgSCHPwrOnPuschGrpPwrForUe  ARGS((
196          RgSchCellCb          *cell,
197          RgSchUeCb            *ue,
198          S8                    delta
199          ));
200 static Bool rgSCHPwrIsDlUeSched ARGS((
201          RgSchCellCb            *cell,
202          RgSchUeCb            *ue,
203          RgSchDlSf            *sf
204          ));
205 static Bool rgSCHPwrIsUlUeSched ARGS((
206          RgSchCellCb          *cell,
207          RgSchUeCb            *ue,
208          RgSchUlSf            *sf
209          ));
210 static Void rgSCHPwrOnSchedPucchTpc ARGS((
211          RgSchCellCb           *cell,
212          RgSchUeCb             *ue,
213          S8                     delta
214          ));
215 static Void rgSCHPwrOnSchedPuschTpc ARGS((
216          RgSchCellCb           *cell,
217          RgSchUeCb             *ue
218          ));
219 static S16 rgSCHPwrApplyUePwrCfg  ARGS((
220          RgSchCellCb          *cell,
221          RgSchUeCb            *ue,
222          RgrUeUlPwrCfg        *pwrCfg
223          ));
224 static Void rgSCHPwrUeResetPucch ARGS((
225          RgSchCellCb          *cell,
226          RgSchUeCb            *ue
227          ));
228 static Void rgSCHPwrUeResetPusch ARGS((
229          RgSchCellCb          *cell,
230          RgSchUeCb            *ue
231          ));
232 static Void rgSCHPwrOnPuschPwrUpd ARGS((
233          RgSchCellCb          *cell,
234          RgSchUeCb            *ue
235          ));
236 static Void rgSCHPwrAddRntiToPucchRntiLst  ARGS((
237          RgSchCellCb          *cell,
238          CmLteRnti             rnti,
239          Bool                  isFmt3a
240          ));
241 static Void rgSCHPwrAddRntiToPuschRntiLst  ARGS((
242          RgSchCellCb          *cell,
243          CmLteRnti             rnti,
244          Bool                  isFmt3a
245          ));
246 static Void rgSCHPwrInitTpcRntiCb  ARGS((
247          RgSchCmnTpcRntiCb    *cb,
248          CmLteRnti             rnti,
249          Bool                  isFmt3a
250          ));
251 static RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb ARGS((
252          RgSchCellCb *cell,
253          CmLteRnti   tpcRnti
254          ));
255 static RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb ARGS((
256          RgSchCellCb *cell,
257          CmLteRnti   tpcRnti
258          ));
259 static Void rgSCHPwrAddUeToPucchTpcRntiCb ARGS((
260          RgSchCellCb           *cell,
261          RgSchCmnTpcRntiCb     *cb,
262          RgSchUeCb             *ue
263          ));
264 static Void rgSCHPwrDelUeFrmPucchTpcRntiCb ARGS((
265          RgSchCellCb           *cell,
266          RgSchCmnTpcRntiCb     *cb,
267          RgSchUeCb             *ue
268          ));
269 static Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb ARGS((
270          RgSchCellCb           *cell,
271          RgSchCmnTpcRntiCb     *cb,
272          RgSchUeCb             *ue
273          ));
274 static Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb ARGS((
275          RgSchCellCb           *cell,
276          RgSchCmnTpcRntiCb     *cb,
277          RgSchUeCb             *ue
278          ));
279 static Void rgSCHPwrRmvSchdPucchTpcRntiCb ARGS((
280          RgSchCellCb           *cell,
281          RgSchCmnTpcRntiCb     *cb
282          ));
283 static Void rgSCHPwrAddSchdUeToPucchTpcRntiCb ARGS((
284          RgSchCellCb           *cell,
285          RgSchCmnTpcRntiCb     *cb,
286          RgSchUeCb             *ue
287          ));
288 static Void rgSCHPwrAddSchdPucchTpcRntiCb ARGS((
289          RgSchCellCb           *cell,
290          RgSchCmnTpcRntiCb     *cb
291          ));
292 static Void rgSCHPwrAddUeToPuschTpcRntiCb ARGS((
293          RgSchCmnTpcRntiCb     *cb,
294          RgSchUeCb             *ue
295          ));
296 static Void rgSCHPwrAddSchdUeToPuschTpcRntiCb ARGS((
297          RgSchCellCb           *cell,
298          RgSchCmnTpcRntiCb     *cb,
299          RgSchUeCb             *ue
300          ));
301 static Void rgSCHPwrDelUeFrmPuschTpcRntiCb ARGS((
302          RgSchCellCb           *cell,
303          RgSchCmnTpcRntiCb     *cb,
304          RgSchUeCb             *ue
305          ));
306 static Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb ARGS((
307          RgSchCellCb           *cell,
308          RgSchCmnTpcRntiCb     *cb,
309          RgSchUeCb             *ue
310          ));
311 static Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb ARGS((
312          RgSchCellCb           *cell,
313          RgSchCmnTpcRntiCb     *cb,
314          RgSchUeCb             *ue
315          ));
316 static Void rgSCHPwrAddSchdPuschTpcRntiCb ARGS((
317          RgSchCellCb           *cell,
318          RgSchCmnTpcRntiCb     *cb
319          ));
320 static Void rgSCHPwrRmvSchdPuschTpcRntiCb ARGS((
321          RgSchCellCb           *cell,
322          RgSchCmnTpcRntiCb     *cb
323          ));
324 static S16 rgSCHPwrChkPucchTpcRntiIdx ARGS((
325          RgSchCmnTpcRntiCb     *cb,
326          uint8_t                     idx
327          ));
328 static S16 rgSCHPwrChkPuschTpcRntiIdx ARGS((
329          RgSchCmnTpcRntiCb     *cb,
330          uint8_t                     idx
331          ));
332 static S16 rgSCHPwrChkUniqPucchTpcRntiIdx ARGS((
333          RgSchCmnTpcRntiCb     *cb,
334          uint8_t                     idx
335          ));
336 static S16 rgSCHPwrChkUniqPuschTpcRntiIdx ARGS((
337          RgSchCmnTpcRntiCb     *cb,
338          uint8_t                     idx
339          ));
340 static S16 rgSCHPwrChkTpcRntiIdx ARGS((
341          RgSchCmnTpcRntiCb     *cb,
342          uint8_t                     idx
343          ));
344 static S8 rgSCHPwrGetPhValFromPhr ARGS((
345          uint8_t                    phr
346          ));
347 static S8 rgSCHPwrGetPCMaxValFromPCMax ARGS((
348          uint8_t                    pCMax
349          ));
350
351 /* local defines */
352
353
354 /**
355  * @brief Does power related initialisation (not cell specific).
356  *        
357  *
358  * @details
359  *
360  *     Function : rgSCHPwrInit
361  *
362  *     Processing Steps:
363  *      - This shall precompute coding efficiency to power
364  *        mappings (assuming beta of 1).
365  *
366  *  @return  Void
367  **/
368 Void rgSCHPwrInit()
369 {
370    uint8_t             idx;
371
372    rgSchPwrCqiToPwrTbl[0] = 0;  /* This should never be used anyway */
373    for (idx = 1; idx < RG_SCH_CMN_UL_NUM_CQI; ++idx)
374    {
375       rgSchPwrCqiToPwrTbl[idx] = rgSCHPwrCalcEfficncyPwr(rgSchCmnUlCqiTbl[idx].eff);
376    }
377    return;
378 }
379
380 /***********************************************************
381  *
382  *     Func : rgSCHPwrGetCqiPwr
383  *
384  *     Desc : Returns power corresponding to coding efficiency
385  *            when beta pusch is assumed 1.
386  *
387  *     Ret  : uint8_t
388  *
389  *     Notes:
390  *
391  *     File :
392  *
393  **********************************************************/
394 static S8 rgSCHPwrGetCqiPwr(uint8_t  cqi)
395 {
396
397    return (rgSchPwrCqiToPwrTbl[cqi]);
398 }  /* rgSCHPwrGetCqiPwr */
399
400 /***********************************************************
401  *
402  *     Func : rgSCHPwrGetCqiPwrForUe
403  *
404  *     Desc : If MCS control is enabled for UE, returns
405  *            power corresponding to CQI, else 0.
406  *
407  *     Ret  : uint8_t
408  *
409  *     Notes:
410  *
411  *     File :
412  *
413  **********************************************************/
414 static S8 rgSCHPwrGetCqiPwrForUe(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t  cqi)
415 {
416    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
417
418    if (!uePwr->deltaMcsEnbld)
419    {
420       return (0);
421    }
422    return (rgSCHPwrGetCqiPwr(cqi));
423 }  /* rgSCHPwrGetCqiPwrForUe */
424
425 /***********************************************************
426  *
427  *     Func : rgSCHPwrCalcEfficncyPwr
428  *
429  *     Desc : Computes power corresponding to a coding
430  *            efficiency.
431  *
432  *     Ret  : uint8_t
433  *
434  *     Notes: Assumes beta pusch to be 1
435  *
436  *     File :
437  *
438  **********************************************************/
439 static S8 rgSCHPwrCalcEfficncyPwr(uint32_t  eff)
440 {
441    F64          ks = 1.25; /* or F64 */
442    F64          tmp = cmPow(2, ks*eff/1024) - 1;
443
444    if (tmp <= 0)
445       return (0);
446    return ((S8)(10 * cmLog10(tmp)));
447 }  /* rgSCHPwrCalcEfficncyPwr */
448
449
450 /**
451  * @brief Returns TPC to be sent in UL allocation
452  *
453  * @details
454  *
455  *     Function : rgSCHPwrPuschTpcForUe
456  *
457  *     Invoking Module Processing:
458  *      - After allocation for UE, this function shall
459  *        be invoked to retrieve TPC.
460  *      - This assumes that rgSCHPwrGetMaxUlRb() was
461  *        invoked prior to final allocation for UE.
462  *        
463  *     Processing Steps:
464  *     - Just return TPC that was determined
465  *       earlier.
466  *     - After this, do necessary updates.
467  *
468  *  @param[in]  RgSchCellCb  *cell
469  *  @param[in]  RgSchUeCb    *ue
470  *  @return  uint8_t
471  **/
472 uint8_t rgSCHPwrPuschTpcForUe(RgSchCellCb *cell,RgSchUeCb   *ue)
473 {
474    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue,cell);
475
476    UNUSED(cell);
477
478    rgSCHPwrOnSchedPuschTpc(cell, ue);
479    return (uePwr->puschTpc);
480 }
481
482 /**
483  * @brief Handles Pusch power control for DCI format 0
484  *
485  * @details
486  *
487  *     Function : rgSCHPwrGetMaxUlRb
488  *
489  *     Invoking Module Processing:
490  *      - This shall be invoked to determine maximum
491  *        number of UL RBs for scheduling.
492  *      - This is expected to be invoked every time
493  *        priority to attempt at UE allocation. Later
494  *        TPC retrieval depends on it.
495  *
496  *     Processing Steps:
497  *     - Returns maximum allowed UL RBs to be granted
498  *       after invoking Pusch power control.
499  *
500  *  @param[in]  RgSchCellCb  *cell
501  *  @param[in]  RgSchUeCb    *ue
502  *  @return  Void
503  **/
504 uint8_t rgSCHPwrGetMaxUlRb(RgSchCellCb *cell,RgSchUeCb   *ue)
505 {
506    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
507
508    rgSCHPwrPuschCntrl(cell, ue); /* This stores tpc, delta and maxRb
509                                   * in uePwr */
510    return (uePwr->maxUlRbs);
511 }
512
513 /**
514  * @brief Handles Pusch power control for DCI format 0
515  *
516  * @details
517  *
518  *     Function : rgSCHPwrPuschCntrl
519  *
520  *     Invoking Module Processing:
521  *      - This shall be invoked to determine TPC
522  *      and maximum number of UL RBs for scheduling
523  *      (through DCI format 0).
524  *
525  *     Processing Steps:
526  *     - 'remPuschPwr' is the final delta power that the UE
527  *       should apply to get to target CQI.
528  *     - The available headroom (availPwr) is determined.
529  *     - Power command is given by considering remPuschPwr and
530  *       availPwr.
531  *     - After factoring in the power command into availPwr, the
532  *       maximum number of RBs that can be supported is determined
533  *       assuming that UE is going to use transmission efficiency
534  *       corresponding to current CQI.
535  *     - The results determined in this function are stored
536  *       in the UE power control block.
537  *     - [Not doing anything of power control of msg3
538  *        retransmissions now]
539  *
540  *  @param[in]  RgSchCellCb  *cell
541  *  @param[in]  RgSchUeCb    *ue
542  *  @return  Void
543  **/
544 static Void rgSCHPwrPuschCntrl(RgSchCellCb *cell,RgSchUeCb   *ue)
545 {
546    RgSchCmnUlUe       *ueUl    = RG_SCH_CMN_GET_UL_UE(ue, cell);
547    RgSchCmnUeUlPwrCb  *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
548    RgSchCmnUlCell     *cellUl  = RG_SCH_CMN_GET_UL_CELL(cell);
549    S8                  delta;
550 #ifdef TFU_UPGRADE
551    uint8_t            cqi     = ueUl->validUlCqi;
552    S32                tmp;
553 #else
554    uint8_t            cqi     = ueUl->crntUlCqi[0];
555 #endif
556    Bool               isAcc   = uePwr->isAccumulated;
557    uint8_t            tpc;
558    S8                 availPwr;
559    uint8_t            maxRb;
560
561    UNUSED(cell);
562
563    if (!uePwr->isPhrAvail)
564    {
565       availPwr = 60; /* setting a large value so that availPwr does
566                       * not constrain delta */
567    }
568    else
569    {
570       availPwr = uePwr->maxUePwr - uePwr->pwrPerRb;
571       availPwr -= rgSCHPwrGetCqiPwrForUe(cell, ue, cqi);
572    }
573    delta = uePwr->remPuschPwr;
574    rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, &tpc, &delta);
575    availPwr -= delta;
576
577    maxRb = rgSCHPwrGetMaxRb(cell,availPwr);
578
579    /* Store the results in ue power control block to be used later */
580    if(maxRb < cellUl->sbSize)
581    {
582        maxRb = cellUl->sbSize;
583 #ifdef TFU_UPGRADE
584        if(uePwr->maxPwrDeltaByPhr < 0)
585        {
586           tmp = ueUl->validUlCqi;
587           tmp = tmp + uePwr->maxPwrDeltaByPhr;
588           if (tmp < 1 )
589           {
590               ueUl->validUlCqi = 1;
591           }
592           else
593           {
594               ueUl->validUlCqi = tmp;
595           }
596        }
597 #endif
598    }
599    DU_LOG("\nDEBUG  -->  SCH : UEID:%d Output Max Rb (%d), phVal (%d) AvailPwr (%d) ",
600          ue->ueId, maxRb, uePwr->phVal, availPwr);
601    DU_LOG("\nDEBUG  -->  SCH : UEID:%d pwrPerRb %d remPuschPwr %d", 
602          ue->ueId,
603          uePwr->pwrPerRb,
604          uePwr->remPuschPwr);
605    uePwr->delta   = delta;
606    uePwr->maxUlRbs = maxRb;
607    uePwr->puschTpc = tpc;
608    return;
609 }
610
611 /**
612  * @brief Returns TPC to be sent in DL allocation
613  *
614  * @details
615  *
616  *     Function : rgSCHPwrPucchTpcForUe
617  *
618  *     Invoking Module Processing:
619  *      - After DL allocation for UE, this function shall
620  *        be invoked to obtain TPC.
621  *
622  *     Processing Steps:
623  *     - Do Pucch power control processing
624  *       and return TPC
625  *
626  *  @param[in]  RgSchCellCb  *cell
627  *  @param[in]  RgSchUeCb    *ue
628  *  @return  uint8_t
629  **/
630 uint8_t rgSCHPwrPucchTpcForUe(RgSchCellCb *cell,RgSchUeCb   *ue)
631 {
632    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
633
634    rgSCHPwrPucchCntrl(cell, ue);
635    return (uePwr->pucchTpc);
636 }
637
638 /***********************************************************
639  *
640  *     Func : rgSCHPwrGetDelta2FrmCqi
641  *
642  *     Desc : Get power to be applied to achieve
643  *            target CQI (the power returned is
644  *            twice is actual power)
645  *
646  *     Ret  : S8
647  *
648  *     Notes:
649  *
650  *     File :
651  *
652  **********************************************************/
653 static S8 rgSCHPwrGetDelta2FrmCqi(uint8_t crntCqi,uint8_t trgCqi,RgSchUeCb *ue,RgSchCellCb *cell)
654 {
655    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
656  
657    if (uePwr->isPhrAvail)
658    {
659       //uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb - uePwr->remPuschPwr;
660       uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb;
661    }
662    else
663    {
664       uePwr->maxPwrDeltaByPhr = 0;         
665    }
666    
667    if (uePwr->maxPwrDeltaByPhr < 0 && (trgCqi - crntCqi) * 
668          RG_SCH_UL_CQI_DB_STEP_2 > 0)
669    {
670       return (0);
671    }
672    return (RGSCH_MIN(uePwr->maxPwrDeltaByPhr, 
673            (trgCqi - crntCqi) * RG_SCH_UL_CQI_DB_STEP_2));
674 }  /* rgSCHPwrGetDelta2FrmCqi */
675
676 /***********************************************************
677  *
678  *     Func : rgSCHPwrGetPuschTpc
679  *
680  *     Desc : Based on whether accumulation is enabled or
681  *            not, this returns an applicable power delta
682  *            to be applied based on the input delta.
683  *
684  *     Ret  : S8
685  *
686  *     Notes:
687  *
688  *     File :
689  *
690  **********************************************************/
691 static Void rgSCHPwrGetPuschTpc(uint8_t isAcc,S8 delta,S8 availPwr,uint8_t *tpc,S8  *tpcDelta)
692 {
693
694    delta = RGSCH_MIN(delta, availPwr);
695
696    /* As of now, the functions below possibly cause delta
697     * to be breached by 1 only. So calling these as is. */
698    if (isAcc)
699    {
700       rgSCHPwrGetAcc2bitTpc(delta, tpc, tpcDelta);
701    }
702    else
703    {
704       rgSCHPwrGetAbsTpc(delta, tpc, tpcDelta);
705    }
706    return;
707 }  /* rgSCHPwrGetPuschTpc */
708
709 /***********************************************************
710  *
711  *     Func : rgSCHPwrGetMaxRb
712  *
713  *     Desc : Get the maximum number of RBs that can be
714  *            expected to be supported by the passed
715  *            power headroom.
716  *
717  *     Ret  : uint8_t
718  *
719  *     Notes:
720  *
721  *     File :
722  *
723  **********************************************************/
724 static uint8_t rgSCHPwrGetMaxRb(RgSchCellCb *cell,S8 pwr)
725 {
726    RgSchCmnUlCell  *cellUl;
727
728    cellUl    = RG_SCH_CMN_GET_UL_CELL(cell);
729    if (pwr <= 0)
730    {
731       /* Give 4 RBS so that UE can report changed power status*/
732       /* [ccpu00119916] Mod -return 0th index of rgSchPwrToRbTbl when pwr <=0
733        *  Change the Macros from RGSCH_MAX_DL_BW to RGSCH_MAX_UL_BW*/
734       return (rgSchPwrToRbTbl[0]);
735    }
736    if (pwr > rgSchPwrRbToPwrTbl[cellUl->maxUlBwPerUe])
737    {
738       return (cellUl->maxUlBwPerUe);
739    }
740    return (RGSCH_MIN(cellUl->maxUlBwPerUe,rgSchPwrToRbTbl[(uint8_t)pwr]));
741 }  /* rgSCHPwrGetMaxRb */
742
743 /***********************************************************
744  *
745  *     Func : rgSCHPwrRbToPwr
746  *
747  *     Desc : Get the power corresponding to number of RBs
748  *
749  *     Ret  : uint8_t
750  *
751  *     Notes:
752  *
753  *     File :
754  *
755  **********************************************************/
756 static uint8_t rgSCHPwrRbToPwr(RgSchCellCb *cell,uint8_t numRb)
757 {
758 #ifndef NO_ERRCLS
759    RgSchCmnUlCell  *cellUl;
760 #endif
761 #if (ERRCLASS & ERRCLS_DEBUG)
762    cellUl    = RG_SCH_CMN_GET_UL_CELL(cell);
763    if (numRb > cellUl->maxUlBwPerUe)
764    {
765       numRb = cellUl->maxUlBwPerUe;
766    }
767 #endif
768    return (rgSchPwrRbToPwrTbl[numRb]);
769 }  /* rgSCHPwrRbToPwr */
770
771
772 /**
773  * @brief Handles Pucch power control for DCI formats 1A/1B/1D/1/2A/2 
774  *
775  * @details
776  *
777  *     Function : rgSCHPwrPucchCntrl
778  *
779  *     Processing Steps:
780  *     - Determine 2 bit TPC to be sent using remPucchPwr.
781  *     - Update remPucchPwr appropriately
782  *
783  *  @param[in]  RgSchCellCb  *cell
784  *  @param[in]  RgSchUeCb    *ue
785  *  @return  Void
786  **/
787 static Void rgSCHPwrPucchCntrl(RgSchCellCb *cell,RgSchUeCb   *ue)
788 {
789    S8                     delta;
790    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
791
792    rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, &uePwr->pucchTpc, &delta);
793    rgSCHPwrOnSchedPucchTpc(cell, ue, delta);
794    return;
795 }
796
797 /**
798  * @brief Handles group power control for DCI formats 3/3A for Pucch and Pusch
799  *
800  * @details
801  *
802  *     Function : rgSCHPwrGrpCntrlPucch
803  *
804  *     Invoking Module Processing:
805  *      - This shall be invoked to do group power control for
806  *        all TPC RNTIs for which it is deemed necessary to
807  *        do the same (group power control).
808  *      - This function should only be invoked after all UEs
809  *        have been scheduled for uplink (re)transmissions
810  *        requiring DL DCI format in the passed subframe.
811  *
812  *     Processing Steps:
813  *     - For Pucch group power control
814  *       - For each TPC-Pucch-RNTI in the pucchGrpPwr List and 
815  *         TPC-Pusch-RNTI in the puschGrpPwr List,
816  *          - Request for PDCCH, skip if not available
817  *          - Form DCI format 3/3A information depending
818  *            on the format type of the TPC-RNTI and add it to the sub-frame.
819  *          - For each Ue in ueLst of TPC RNTI Cb
820  *             - if (fmtType == 3A)
821  *              - if((Ue not scheduled DL dci formats)
822  *                     && (remPwr >= 2 || remPwr <= -2))
823  *                  - Determine TPC. Set puschTpc/pucchTpc.
824  *                  - remPwr -= TPC
825  *                  - if (remPwr >= -1 && remPwr <= 1)
826  *                    - If already added, remove from toBeSchdLst
827  *              - else
828  *                  - Toggle the remainig power value
829  *             - else if (fmtType == 3)
830  *              - if((Ue not scheduled DL dci formats)
831  *                    && (remPwr))
832  *                  - Determine TPC. Set puschTpc/pucchTpc.
833  *                  - remPwr -= TPC
834  *                  - if (!remPwr)
835  *                    - If already added, remove from toBeSchdLst
836  *          - if (!toBeSchdUeCnt)
837  *             - Remove the tpcRntiCb frm pucchGrpPwr/puschGrpPwr List
838  *          - else, Move the tpcRntiCb to end of the list (not doing
839  *             this)
840  *
841  *  @param[in]  RgSchCellCb  *cell
842  *  @param[in]  RgSchDlSf    *dlSf
843  *  @return  Void
844  **/
845 Void rgSCHPwrGrpCntrlPucch(RgSchCellCb *cell,RgSchDlSf   *dlSf)
846 {
847    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
848    CmLListCp             *lst;
849    CmLList               *lnk;
850    RgSchPdcch            *pdcch;
851
852    lst = &cellPwr->pucchGrpPwr;
853    lnk = lst->first;
854    while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
855    {
856       RgSchCmnTpcRntiCb      *cb = (RgSchCmnTpcRntiCb *)lnk->node;
857       Bool                    sched;
858       lnk = lnk->next;
859       rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, &sched);
860       if (!sched)
861       {
862          rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
863       }
864       /* TPC RNTI would not have been removed if needs to
865        * be scheduled again */
866    }
867
868    return;
869 }
870
871 /**
872  * @brief Handles group power control for DCI formats 3/3A for Pusch and Pusch
873  *
874  * @details
875  *
876  *     Function : rgSCHPwrGrpCntrlPusch
877  *
878  *     Invoking Module Processing:
879  *      - This shall be invoked to do group power control for
880  *        all TPC RNTIs for which it is deemed necessary to
881  *        do the same (group power control).
882  *      - This function should only be invoked after all UEs
883  *        have been scheduled for uplink (re)transmissions
884  *        requiring DCI format 0 in the passed subframe.
885  *
886  *     Processing Steps:
887  *     - For Pusch group power control
888  *       - For each TPC-Pusch-RNTI in the puschGrpPwr List and 
889  *          - Request for PDCCH, skip if not available
890  *          - Form DCI format 3/3A information depending
891  *            on the format type of the TPC-RNTI and add it to the sub-frame.
892  *          - For each Ue in ueLst of TPC RNTI Cb
893  *             - if (fmtType == 3A)
894  *              - if (Ue not scheduled for dci format 0) and
895  *                (remPwr >= 2 || remPwr <= -2))
896  *                  - Determine TPC. Set puschTpc/puschTpc.
897  *                  - remPwr -= TPC
898  *                  - if (remPwr >= -1 && remPwr <= 1)
899  *                    - If already added, remove from toBeSchdLst
900  *              - else
901  *                  - Toggle the remainig power value
902  *             - else if (fmtType == 3)
903  *              - if((Ue not scheduled for dci format 0) && (remPwr))
904  *                  - Determine TPC. Set puschTpc.
905  *                  - remPwr -= TPC
906  *                  - if (!remPwr)
907  *                    - If already added, remove from toBeSchdLst
908  *          - if (!toBeSchdUeCnt)
909  *             - Remove the tpcRntiCb frm puschGrpPwr/puschGrpPwr List
910  *          - else, Move the tpcRntiCb to end of the list (not doing
911  *            this now)
912  *
913  *  @param[in]  RgSchCellCb  *cell
914  *  @param[in]  RgSchDlSf    *sf
915  *  @return  Void
916  **/
917 Void rgSCHPwrGrpCntrlPusch(RgSchCellCb *cell,RgSchDlSf   *dlSf,RgSchUlSf   *ulSf)
918 {
919    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
920    CmLListCp             *lst;
921    CmLList               *lnk;
922    RgSchPdcch            *pdcch;
923
924    lst = &cellPwr->puschGrpPwr;
925    lnk = lst->first;
926    while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
927    {
928       RgSchCmnTpcRntiCb      *cb = (RgSchCmnTpcRntiCb *)lnk->node;
929       Bool                    sched;
930       lnk = lnk->next;
931       rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, &sched);
932       if (!sched)
933       {
934          rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
935       }
936       /* TPC RNTI would not have been removed if needs to
937        * be scheduled again */
938    }
939
940    return;
941 }
942
943 /***********************************************************
944  *
945  *     Func : rgSCHPwrSchedPucchRnti
946  *
947  *     Desc : Schedule TPC RNTI to be sent out
948  *
949  *     Ret  : Void
950  *
951  *     Notes:
952  *
953  *     File :
954  *
955  **********************************************************/
956 static Void rgSCHPwrSchedPucchRnti(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchPdcch *pdcch,RgSchDlSf *dlSf,Bool *sched)
957 {
958    CmLListCp         *lst;
959    CmLList           *lnk;
960    uint8_t           *tpcCmds;
961    uint8_t           tpc;
962    S8                delta;
963    Bool              atleastOne;
964
965    pdcch->rnti = cb->tpcRnti;
966
967    if (cb->isFmt3a)
968    {
969       /* Go through all UEs for format 3A case */
970       lst = &cb->cfgdUes;
971       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
972       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
973       pdcch->dci.u.format3AInfo.isPucch = TRUE;
974
975       tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
976       /* No need to memset zero initially as every TPC is going
977        * to be filled up for every configured UE */
978       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
979       {
980          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
981          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
982
983          if ( ue->isDrxEnabled == TRUE && 
984                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
985          {
986             /* UE is in its DRX time. So we cannot give command
987              * to this UE.
988              */
989             continue;
990          }
991
992          if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
993          {
994             /* UE already scheduled in downlink with PDCCH
995              * carrying PUCCH pwr cmd. So don't care about
996              * giving command to this UE. */
997             continue;
998          }
999          rgSCHPwrGetPucchFmt3aTpcForUe(ue, &tpc, &delta);
1000          tpcCmds[uePwr->pucchIdx] = tpc;
1001          atleastOne = TRUE;
1002          rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1003       }
1004    }
1005    else
1006    {
1007       /* Go through to-be-scheduled UEs for format 3 case */
1008       lst = &cb->toBeSchdUes;
1009       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1010       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1011       tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1012       pdcch->dci.u.format3Info.isPucch = TRUE;
1013
1014       /* Fill TPC 1 (corresponding to no power change) initially */
1015       memset(tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1016
1017       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1018       {
1019          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1020          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1021
1022          if ( ue->isDrxEnabled == TRUE && 
1023                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1024          {
1025             /* UE is in its DRX time. So we cannot give command
1026              * to this UE.
1027              */
1028             continue;
1029          }
1030
1031          if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1032          {
1033             /* UE already scheduled in downlink with PDCCH
1034              * carrying PUCCH pwr cmd. So don't care about
1035              * giving command to this UE. */
1036             continue;
1037          }
1038          rgSCHPwrGetPucchFmt3TpcForUe(ue, &tpc, &delta);
1039          tpcCmds[uePwr->pucchIdx] = tpc;
1040          atleastOne = TRUE;
1041          rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1042       }
1043    }
1044
1045    *sched = atleastOne;
1046
1047    /* Check if no more UEs in TPC RNTI, and then remove
1048     * this TPC RNTI from scheduled list */
1049     if (cb->toBeSchdUes.count == 0)
1050     {
1051        rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
1052     }
1053
1054    return;
1055 }  /* rgSCHPwrSchedPucchRnti */
1056
1057 /***********************************************************
1058  *
1059  *     Func : rgSCHPwrSchedPuschRnti
1060  *
1061  *     Desc : Schedule TPC RNTI to be sent out
1062  *
1063  *     Ret  : Void
1064  *
1065  *     Notes:
1066  *
1067  *     File :
1068  *
1069  **********************************************************/
1070 static Void rgSCHPwrSchedPuschRnti(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchPdcch *pdcch,RgSchUlSf *ulSf,Bool  *sched)
1071 {
1072    CmLListCp         *lst;
1073    CmLList           *lnk;
1074    uint8_t           *tpcCmds;
1075    uint8_t           tpc;
1076    S8                delta;
1077    Bool              atleastOne;
1078
1079    pdcch->rnti = cb->tpcRnti;
1080
1081    if (cb->isFmt3a)
1082    {
1083       /* Go through all UEs for format 3A case */
1084       lst = &cb->cfgdUes;
1085       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1086       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1087       pdcch->dci.u.format3AInfo.isPucch = FALSE;
1088       tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1089       /* No need to memset zero initially as every TPC is going
1090        * to be filled up for every configured UE */
1091       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1092       {
1093          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1094          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1095          if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1096          {
1097             /* UE already scheduled in uplink with DCI
1098              * format 0. So don't care about giving
1099              * command to this UE. */
1100             continue;
1101          }
1102
1103          if ( ue->isDrxEnabled == TRUE && 
1104                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1105          {
1106             /* UE is in its DRX time. So we cannot give command
1107              * to this UE.
1108              */
1109             continue;
1110          }
1111
1112          rgSCHPwrGetPuschFmt3aTpcForUe(ue, &tpc, &delta);
1113          tpcCmds[uePwr->puschIdx] = tpc;
1114          atleastOne = TRUE;
1115          rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1116       }
1117    }
1118    else
1119    {
1120       /* Go through to-be-scheduled UEs for format 3 case */
1121       lst = &cb->toBeSchdUes;
1122       pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1123       pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1124       pdcch->dci.u.format3Info.isPucch = FALSE;
1125       tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1126
1127       /* Fill TPC 1 (corresponding to no power change) initially */
1128       memset(tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1129
1130       for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1131       {
1132          RgSchUeCb             *ue    = (RgSchUeCb *)lnk->node;
1133          RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1134          if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1135          {
1136             /* UE already scheduled in uplink with DCI
1137              * format 0. So don't care about giving
1138              * command to this UE. */
1139             continue;
1140          }
1141
1142          if ( ue->isDrxEnabled == TRUE && 
1143                !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1144          {
1145             /* UE is in its DRX time. So we cannot give command
1146              * to this UE.
1147              */
1148             continue;
1149          }
1150
1151          rgSCHPwrGetPuschFmt3TpcForUe(ue, &tpc, &delta);
1152          tpcCmds[uePwr->puschIdx] = tpc;
1153          atleastOne = TRUE;
1154          rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1155       }
1156    }
1157
1158    *sched = atleastOne;
1159
1160    /* Check if no more UEs in TPC RNTI, and then remove
1161     * this TPC RNTI from scheduled list */
1162     if (cb->toBeSchdUes.count == 0)
1163     {
1164        rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
1165     }
1166
1167    return;
1168 }  /* rgSCHPwrSchedPuschRnti */
1169
1170 /***********************************************************
1171  *
1172  *     Func : rgSCHPwrGetPucchFmt3TpcForUe
1173  *
1174  *     Desc : Gets 2 bit TPC cmd for PUCCH
1175  *
1176  *     Ret  : Void
1177  *
1178  *     Notes:
1179  *
1180  *     File :
1181  *
1182  **********************************************************/
1183 static Void rgSCHPwrGetPucchFmt3TpcForUe(RgSchUeCb *ue,uint8_t  *tpc,S8 *delta)
1184 {
1185    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1186
1187    rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, tpc, delta);
1188    return;
1189 }  /* rgSCHPwrGetPucchFmt3TpcForUe */
1190
1191 /***********************************************************
1192  *
1193  *     Func : rgSCHPwrGetPucchFmt3aTpcForUe
1194  *
1195  *     Desc : Gets 1 bit TPC cmd for PUCCH
1196  *
1197  *     Ret  : Void
1198  *
1199  *     Notes:
1200  *
1201  *     File :
1202  *
1203  **********************************************************/
1204 static Void rgSCHPwrGetPucchFmt3aTpcForUe(RgSchUeCb *ue,uint8_t *tpc,S8 *delta)
1205 {
1206    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1207
1208    rgSCHPwrGetAcc1bitTpc(uePwr->remPucchPwr, tpc, delta);
1209    return;
1210 }  /* rgSCHPwrGetPucchFmt3aTpcForUe */
1211
1212 /***********************************************************
1213  *
1214  *     Func : rgSCHPwrGetPuschFmt3TpcForUe
1215  *
1216  *     Desc : Gets 2 bit TPC cmd for PUCCH
1217  *
1218  *     Ret  : Void
1219  *
1220  *     Notes:
1221  *
1222  *     File :
1223  *
1224  **********************************************************/
1225 static Void rgSCHPwrGetPuschFmt3TpcForUe(RgSchUeCb *ue,uint8_t *tpc,S8 *delta)
1226 {
1227    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1228    S8                     adj = RGSCH_MIN(uePwr->remPuschPwr, uePwr->phVal);
1229
1230    rgSCHPwrGetAcc2bitTpc(adj, tpc, delta);
1231    return;
1232 }  /* rgSCHPwrGetPuschFmt3TpcForUe */
1233
1234 /***********************************************************
1235  *
1236  *     Func : rgSCHPwrGetPuschFmt3aTpcForUe
1237  *
1238  *     Desc : Gets 1 bit TPC cmd for PUCCH
1239  *
1240  *     Ret  : Void
1241  *
1242  *     Notes:
1243  *
1244  *     File :
1245  *
1246  **********************************************************/
1247 static Void rgSCHPwrGetPuschFmt3aTpcForUe(RgSchUeCb *ue,uint8_t *tpc,S8 *delta)
1248 {
1249    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1250
1251    /* Don't attempt to look at headroom now, power
1252     * adjustment is small anyway */
1253    rgSCHPwrGetAcc1bitTpc(uePwr->remPuschPwr, tpc, delta);
1254    return;
1255 }  /* rgSCHPwrGetPuschFmt3aTpcForUe */
1256
1257 /***********************************************************
1258  *
1259  *     Func : rgSCHPwrGetAcc1bitTpc
1260  *
1261  *     Desc : Gets 1 bit TPC cmd
1262  *
1263  *     Ret  : Void
1264  *
1265  *     Notes:
1266  *
1267  *     File :
1268  *
1269  **********************************************************/
1270 static Void rgSCHPwrGetAcc1bitTpc(S8 remPwr,uint8_t *tpc,S8 *delta)
1271 {
1272    /*
1273     * TPC   delta
1274     *  0     -1
1275     *  1      1
1276     */
1277    if (remPwr <= 0)
1278    {
1279       *delta = -1;
1280       *tpc = 0;
1281    }
1282    else
1283    {
1284       *delta = 1;
1285       *tpc = 1;
1286    }
1287    return;
1288 }  /* rgSCHPwrGetAcc1bitTpc */
1289
1290 /***********************************************************
1291  *
1292  *     Func : rgSCHPwrGetAcc2bitTpc
1293  *
1294  *     Desc : Allocate PDCCH for group power control
1295  *
1296  *     Ret  : Void
1297  *
1298  *     Notes:
1299  *
1300  *     File :
1301  *
1302  **********************************************************/
1303 static Void rgSCHPwrGetAcc2bitTpc(S8 remPwr,uint8_t *tpc,S8 *delta)
1304 {
1305    /*
1306     * TPC   delta
1307     *  0     -1
1308     *  1      0
1309     *  2      1
1310     *  3      3
1311     */
1312    uint8_t            tpcs[3]   = {1, 2, 2};
1313    uint8_t            deltas[3] = {0, 1, 1};
1314    if (remPwr <= -1)
1315    {
1316       *tpc   = 0;
1317       *delta = -1;
1318    }
1319    else if (remPwr >= 3)
1320    {
1321       *tpc   = 3;
1322       *delta = 3;
1323    }
1324    else
1325    {
1326       *tpc   = tpcs[(uint8_t)remPwr];
1327       *delta = deltas[(uint8_t)remPwr];
1328    }
1329    return;
1330 }  /* rgSCHPwrGetAcc2bitTpc */
1331
1332 /***********************************************************
1333  *
1334  *     Func : rgSCHPwrGetAbsTpc
1335  *
1336  *     Desc : Allocate PDCCH for group power control
1337  *
1338  *     Ret  : Void
1339  *
1340  *     Notes:
1341  *
1342  *     File :
1343  *
1344  **********************************************************/
1345 static Void rgSCHPwrGetAbsTpc(S8 remPwr,uint8_t *tpc,S8 *delta)
1346 {
1347    /*
1348     * TPC   delta
1349     *  0     -4
1350     *  1     -1
1351     *  2      1
1352     *  3      4
1353     */
1354    if (remPwr <= -3)
1355    {
1356       *tpc = 0;
1357       *delta = -4;
1358    }
1359    else if (remPwr < 1)
1360    {
1361       *tpc = 1;
1362       *delta = -1;
1363    }
1364    else if (remPwr < 4)
1365    {
1366       *tpc = 2;
1367       *delta = 1;
1368    }
1369    else
1370    {
1371       *tpc = 3;
1372       *delta = 4;
1373    }
1374    return;
1375 }  /* rgSCHPwrGetAbsTpc */
1376
1377 /***********************************************************
1378  *
1379  *     Func : rgSCHPwrOnPucchGrpPwrForUe
1380  *
1381  *     Desc : Processing on sending TPC for UE through group power
1382  *            control. Apart from updating remPwr, this only takes
1383  *            care of possibly removing UE from scheduled
1384  *            list in TPC RNTI.
1385  *            It does not take care of possibly removing TPC RNTI
1386  *            from scheduled list in cell. This is done
1387  *            in the caller after TPC for all UEs has been
1388  *            determined. (This is where it differs
1389  *            from the usual OnSendingPu[cs]ch TPC]
1390  *
1391  *     Ret  : ROK/RFAILED
1392  *
1393  *     Notes:
1394  *
1395  *     File :
1396  *
1397  **********************************************************/
1398 static Void rgSCHPwrOnPucchGrpPwrForUe(RgSchCellCb *cell,RgSchUeCb *ue,S8  delta)
1399 {
1400    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1401    Bool                   rmvUe = FALSE;
1402
1403    UNUSED(cell);
1404
1405    uePwr->remPucchPwr -= delta;
1406
1407    /* UE was already scheduled for PUCCH group power
1408     * control which is why we came here. Don't
1409     * again check for this. */
1410
1411    /* UE was scheduled for pucch grp pwr, sent TPC may
1412     * possibly cause it to be removed. */
1413       if (!uePwr->remPucchPwr)
1414       {
1415          rmvUe = TRUE;
1416       }
1417    if (rmvUe)
1418    {
1419       rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
1420       /* Not removing TPC RNTI from scheduled list,
1421        * this will happen in the caller once this
1422        * function is called for every UE scheduled. */
1423    }
1424    return;
1425 }
1426
1427 /***********************************************************
1428  *
1429  *     Func : rgSCHPwrOnPuschGrpPwrForUe
1430  *
1431  *     Desc : Processing on sending TPC for UE through group power
1432  *            control. Apart from updating remPwr, this only takes
1433  *            care of possibly removing UE from scheduled
1434  *            list in TPC RNTI.
1435  *            It does not take care of possibly removing TPC RNTI
1436  *            from scheduled list in cell. This is done
1437  *            in the caller after TPC for all UEs has been
1438  *            determined. (This is where it differs
1439  *            from the usual OnSendingPu[cs]ch TPC]
1440  *
1441  *     Ret  : ROK/RFAILED
1442  *
1443  *     Notes:
1444  *
1445  *     File :
1446  *
1447  **********************************************************/
1448 static Void rgSCHPwrOnPuschGrpPwrForUe(RgSchCellCb *cell,RgSchUeCb *ue,S8 delta)
1449 {
1450    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1451    Bool                   rmvUe = FALSE;
1452
1453    UNUSED(cell);
1454
1455    uePwr->delta = delta;
1456    uePwr->remPuschPwr -= delta;
1457    if (uePwr->isPhrAvail)
1458    {
1459       uePwr->phVal -= uePwr->delta;
1460       uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1461    }
1462
1463    /* UE was already scheduled for PUSCH group power
1464     * control which is why we came here. Don't
1465     * again check for this. */
1466
1467    /* UE was scheduled for pusch grp pwr, sent TPC may
1468     * possibly cause it to be removed. */
1469
1470       if (!uePwr->remPuschPwr)
1471       {
1472          rmvUe = TRUE;
1473       }
1474
1475    if (rmvUe)
1476    {
1477       rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
1478       /* Not removing TPC RNTI from scheduled list,
1479        * this will happen in the caller once this
1480        * function is called for every UE scheduled. */
1481    }
1482    return;
1483 }
1484
1485 /***********************************************************
1486  *
1487  *     Func : rgSCHPwrIsDlUeSched
1488  *
1489  *     Desc : Check if UE is scheduled in the passed DL SF
1490  *
1491  *     Ret  : Void
1492  *
1493  *     Notes:
1494  *
1495  *     File :
1496  *
1497  **********************************************************/
1498 static Bool rgSCHPwrIsDlUeSched(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlSf  *sf)
1499 {
1500    RgSchDlHqEnt          *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1501    RgSchDlHqProcCb      *proc    = rgSCHDhmLastSchedHqProc(hqEnt);
1502
1503    if (proc == NULLP)
1504    {
1505       return (FALSE);
1506    }
1507
1508    /*
1509     * The following subframe check is assumed enough, since
1510     * scheduled procs stay for a short time (until feedback
1511     * arrives), which typically is expected to have a
1512     * turnaround time of less than 8 subframes. So
1513     * we are probably never going to come across cases
1514     * where a process stays in the list for more than
1515     * 10 subframes, which would have otherwise caused
1516     * the check to succeed for a possibly older process.
1517     */
1518    if ((proc->tbInfo[0].timingInfo.slot == sf->sfNum) ||
1519        (proc->tbInfo[1].timingInfo.slot == sf->sfNum))
1520    {
1521       /*
1522        * Later, if a proc can be scheduled without having an
1523        * associated PDCCH, need to also check if PDCCH exists.
1524        * This is because for power, what matters is whether
1525        * TPC is going out for UE at this time or not, at least
1526        * that is what this function was introduced for.
1527        * Checking for PDCCH would have to be in common proc
1528        * the way things are now.
1529        */
1530       return (TRUE);
1531    }
1532    else
1533    {
1534       return (FALSE);
1535    }
1536 }  /* rgSCHPwrIsDlUeSched */
1537
1538 /***********************************************************
1539  *
1540  *     Func : rgSCHPwrIsUlUeSched
1541  *
1542  *     Desc : Check if UE is scheduled in the passed UL SF
1543  *
1544  *     Ret  : Void
1545  *
1546  *     Notes:
1547  *
1548  *     File :
1549  *
1550  **********************************************************/
1551 static Bool rgSCHPwrIsUlUeSched(RgSchCellCb  *cell,RgSchUeCb *ue,RgSchUlSf *sf)
1552 {
1553    RgSchCmnUlCell      *cmnCell = RG_SCH_CMN_GET_UL_CELL(cell);
1554    RgSchUlHqProcCb     *proc = rgSCHUhmGetUlHqProc(cell, ue, cmnCell->schdHqProcIdx);
1555
1556    UNUSED(sf);
1557
1558 #if (ERRCLASS & ERRCLS_DEBUG)
1559    if( proc == NULLP )
1560    {
1561       return  (FALSE);
1562    }
1563 #endif  
1564
1565    if (proc->alloc)
1566    {
1567       return (TRUE);
1568    }
1569    else
1570    {
1571       return (FALSE);
1572    }
1573 }  /* rgSCHPwrIsUlUeSched */
1574
1575 /**
1576  * @brief Handles Pucch power delta indication recieved from PHY
1577  *
1578  * @details
1579  *
1580  *     Function : rgSCHPwrPucchDeltaInd
1581  *
1582  *     Invoking Module Processing:
1583  *      - This shall be invoked on reception of Pucch power 
1584  *        delta indication from PHY.
1585  *        
1586  *     Processing Steps:
1587  *     - Update the remPucchPwr 
1588  *       ue->remPucchPwr = pwrDelta
1589  *     - If (ue->tpcPucchRntiCb)
1590  *       - If (fmtType = 3A)
1591  *          - if (remPucchPwr >= 2 || remPucchPwr <= -2 )
1592  *             - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1593  *               - Add tpcPucchRntiCb to the pucchGrpPwr list.
1594  *             - If not added, add to toBeSchdLst
1595  *          - else
1596  *             - If already added, remove from toBeSchdLst
1597  *       - else If (fmtType == 3) 
1598  *          - if (remPucchPwr)
1599  *             - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1600  *               - Add tpcPucchRntiCb to the pucchGrpPwr list.
1601  *             - If not added, add to toBeSchdLst
1602  *          - else
1603  *             - If already added, remove from toBeSchdLst
1604  *
1605  *  @param[in]  RgSchCellCb  *cell
1606  *  @param[in]  RgSchUeCb    *ue
1607  *  @param[in]  uint8_t           pwrDelta
1608  *  @return  Void
1609  **/
1610 Void rgSCHPwrPucchDeltaInd(RgSchCellCb *cell,RgSchUeCb *ue,S8 pwrDelta)
1611 {
1612    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1613    RgSchCmnTpcRntiCb     *cb;
1614    Bool                   toAdd;
1615
1616    uePwr->remPucchPwr = pwrDelta;
1617    
1618    if ((cb = uePwr->tpcPucchRntiCb) == NULLP)
1619    {
1620       return;
1621    }
1622
1623    toAdd = FALSE;
1624
1625    if (0 != uePwr->remPucchPwr)
1626       {
1627          toAdd = TRUE;
1628       }
1629
1630
1631    if (toAdd)
1632    {
1633       rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue);
1634    }
1635    else
1636    {
1637       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
1638    }
1639
1640    return;
1641 }
1642
1643 /**
1644  * @brief Does processing after TPC for Pucch has been sent
1645  *
1646  * @details
1647  *
1648  *     Function : rgSCHPwrOnSchedPucchTpc
1649  *
1650  *     Invoking Module Processing:
1651  *      - It shall be invoked after it is determined that PDCCH for UE
1652  *        is finalised to go out, and thus TPC for PUCCH is being
1653  *        sent out.
1654  *
1655  *     Processing Steps:
1656  *     - Update remPucchPwr with the delta
1657  *     - Do group power control related processing
1658  *
1659  *  @param[in]  RgSchCellCb       *cell
1660  *  @param[in]  RgSchUeCb         *ue
1661  *  @param[in]  S8                 delta
1662  *  @return  Void
1663  **/
1664 static Void rgSCHPwrOnSchedPucchTpc(RgSchCellCb *cell,RgSchUeCb *ue,S8 delta)
1665 {
1666    /* Similar to rgSCHPwrPucchDeltaInd.. not reusing
1667     * that since we use the fact that UE could only have
1668     * improved its remPwr as part of power control. */
1669    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1670    Bool                   rmvUe = FALSE;
1671
1672    uePwr->remPucchPwr -= delta;
1673
1674    if (uePwr->schdPucchGrpLnk.node == NULLP)
1675    {
1676       return;
1677    }
1678
1679    /* UE was scheduled for TPC, sent TPC may
1680     * possibly cause it to be removed. */
1681
1682       if (!uePwr->remPucchPwr)
1683       {
1684          rmvUe = TRUE;
1685       }
1686
1687    if (rmvUe)
1688    {
1689       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
1690       if (uePwr->tpcPucchRntiCb->toBeSchdUes.count == 0)
1691       {
1692          rgSCHPwrRmvSchdPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb);
1693       }
1694    }
1695    return;
1696 }
1697
1698
1699 /**
1700  * @brief Does processing after TPC for Pusch has been sent
1701  *
1702  * @details
1703  *
1704  *     Function : rgSCHPwrOnSchedPuschTpc
1705  *
1706  *     Processing Steps:
1707  *      - If accumulative
1708  *        - Update remPuschPwr with the delta
1709  *        - Do group power related processing if applicable
1710  *       
1711  *  @param[in]  RgSchCellCb       *cell
1712  *  @param[in]  RgSchUeCb         *ue
1713  *  @return  Void
1714  **/
1715 static Void rgSCHPwrOnSchedPuschTpc(RgSchCellCb  *cell,RgSchUeCb *ue)
1716 {
1717    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1718    Bool                   rmvUe = FALSE;
1719
1720    /* Don't do anything for the case of absolute TPC commands */
1721    if (!uePwr->isAccumulated)
1722    {
1723       return;
1724    }
1725
1726    uePwr->remPuschPwr -= uePwr->delta;
1727    if (uePwr->isPhrAvail)
1728    {
1729       uePwr->phVal -= uePwr->delta;
1730       uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1731    }
1732
1733    if (uePwr->schdPuschGrpLnk.node == NULLP)
1734    {
1735       return;
1736    }
1737
1738    /* UE was scheduled for pusch TPC, sent TPC may
1739     * possibly cause it to be removed. */
1740
1741       if (!uePwr->remPuschPwr)
1742       {
1743          rmvUe = TRUE;
1744       }
1745
1746    if (rmvUe)
1747    {
1748       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
1749    }
1750
1751    return;
1752 }
1753
1754 /**
1755  * @brief Handles PHR updation for the UE
1756  *
1757  * @details
1758  *
1759  *     Function : rgSCHPwrUpdExtPhr
1760  *  @param[in]  RgSchCellCb         *cell
1761  *  @param[in]  RgSchUeCb           *ue
1762  *  @param[in]  RgInfExtPhrCEInfo   *extPhr
1763  *  @param[in]  RgSchCmnAllocRecord  allocInfo
1764  *  @return  Void
1765  **/
1766 Void rgSCHPwrUpdExtPhr(RgSchCellCb  *cell,RgSchUeCb *ue,RgInfExtPhrCEInfo *extPhr,RgSchCmnAllocRecord  *allocInfo)
1767 {
1768    uint8_t idx;
1769    RgInfExtPhrSCellInfo  *servCellPhr;
1770    S8      pCMax;
1771
1772    for (idx = 0; idx < extPhr->numServCells; idx++)
1773    {
1774       servCellPhr = &extPhr->servCellPhr[idx];
1775
1776       if (RG_SCH_REF_PCMAX == servCellPhr->pCmax)
1777       {
1778          pCMax = RG_SCH_CMN_PWR_USE_CFG_MAX_PWR;
1779       }
1780       else
1781       {
1782          pCMax = rgSCHPwrGetPCMaxValFromPCMax(servCellPhr->pCmax);
1783       }
1784       rgSCHPwrUpdPhr(ue->cellInfo[servCellPhr->sCellIdx]->cell,
1785             ue, servCellPhr->phr, allocInfo, pCMax);
1786    }
1787    return;
1788 }
1789
1790 /**
1791  * @brief Handles PHR updation for the UE
1792  *
1793  * @details
1794  *
1795  *     Function : rgSCHPwrUpdPhr
1796  *
1797  *     Invoking Module Processing:
1798  *      - This shall be invoked on reception of PHR from MAC to SCH. It shall
1799  *      pass the information of number of RBs, coding efficiency and TPC for 
1800  *      the Pusch transmission for which PHR has been reported.
1801  *
1802  *     Processing Steps:
1803  *     - Compute power per RB using the PHR report
1804  *        - ue_transmit_pwr = ue_max_pwr - PHR
1805  *        - if isDeltaMcs = TRUE
1806  *          - ue_transmit_pwr - 
1807  *            [10log(phr_num_rb) + 10log(2^ (1.25 * phr_coding_effeciency) -1)
1808  *            + phr_tpc(if absolute TPC)] = pwrPerRB
1809  *        - else
1810  *          - ue_transmit_pwr - [10log(phr_num_rb) + phr_tpc(if absolute TPC)]
1811  *            = pwrPerRB
1812  *        (Use the number of RBs and efficiency used by UE which caused the PHR
1813  *         report to happen)
1814  *     - Adjust PHR according to last allocation (take into account
1815  *       number of RBs granted in the last allocation)
1816  *     - Update the PHR report in the control block
1817  *     - Set isPhrAvail = TRUE
1818  *     - Do group power control related processing if applicable
1819  *
1820  *  @param[in]  RgSchCellCb         *cell
1821  *  @param[in]  RgSchUeCb           *ue
1822  *  @param[in]  uint8_t                   phr
1823  *  @param[in]  RgSchCmnAllocRecord  allocInfo
1824  *  @param[in]  uint8_t                   maxUePwr
1825  *  @return  Void
1826  **/
1827 Void rgSCHPwrUpdPhr(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t phr,RgSchCmnAllocRecord   *allocInfo,S8 maxUePwr )
1828 {
1829    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
1830    uint8_t               rbPwr;
1831    uint8_t               effPwr;
1832    RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
1833
1834    uePwr->phVal = rgSCHPwrGetPhValFromPhr(phr);
1835   
1836    if (maxUePwr == RG_SCH_CMN_PWR_USE_CFG_MAX_PWR)
1837    {
1838       maxUePwr = uePwr->maxUePwr;
1839    }
1840    rbPwr = rgSCHPwrRbToPwr(cell,allocInfo->numRb);
1841    effPwr = rgSCHPwrGetCqiPwrForUe(cell, ue, allocInfo->cqi);
1842    uePwr->pwrPerRb = maxUePwr - uePwr->phVal - rbPwr - effPwr;
1843    /*if (!uePwr->isAccumulated)
1844    {
1845       uePwr->pwrPerRb -= rgSCHPwrGetDeltaFrmAbsTpc(allocInfo->tpc);
1846    }*/
1847
1848    /* Let headroom reflect remaining power according to last
1849     * allocated number of RBs. Intermediate TPCs not yet
1850     * taken care of (for accumulated case, it is anyway
1851     * not applicable for absolute commands). */
1852    uePwr->phVal -= (rgSCHPwrRbToPwr(cell, cellUl->sbSize)) - rbPwr;
1853    uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1854    uePwr->isPhrAvail = TRUE;
1855
1856    rgSCHPwrOnPuschPwrUpd(cell, ue);
1857
1858    DU_LOG("\nDEBUG  -->  SCH : Output: Reported PHR[%d] cqi[%u] allocRb[%u] uePwr->pwrPerRb[%d]",
1859             uePwr->phVal,
1860             allocInfo->cqi,
1861             allocInfo->numRb,  
1862             uePwr->pwrPerRb); 
1863    return;
1864 }
1865
1866 /**
1867  * @brief Handles UL CQI indication
1868  *
1869  * @details
1870  *
1871  *     Function : rgSCHPwrUlCqiInd
1872  *
1873  *     Invoking Module Processing:
1874  *      - This shall be invoked when uplink CQI indication
1875  *        is receiving from PHY for a UE.
1876  *
1877  *     Processing Steps:
1878  *     - Update remPuschPwr.
1879  *     - Possibly schedule for group power control.
1880  *
1881  *  @param[in]  RgSchCellCb         *cell
1882  *  @param[in]  RgSchUeCb           *ue
1883  *  @param[in]  uint8_t                   numRb
1884  *  @return  Void
1885  **/
1886 Void rgSCHPwrUlCqiInd(RgSchCellCb *cell,RgSchUeCb  *ue)
1887 {
1888    RgSchCmnUlUe          *ueUl    = RG_SCH_CMN_GET_UL_UE(ue, cell);
1889    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
1890 #ifdef TFU_UPGRADE 
1891    S32  tmp;
1892 #endif
1893
1894    /*
1895     * For absolute power cmd case, we could look at the time
1896     * at which CQI was received, determine if there was a
1897     * PUSCH TPC cmd for that time (this could come from
1898     * group power control too), and (if this
1899     * CQI report is indeed based on the the PUSCH tx)
1900     * then factor in that cmd here. Not doing
1901     * this as of now.
1902     */
1903
1904    /* See how much power needs to be adjusted based on cqi
1905     * differential */
1906    uePwr->remPuschPwr = 
1907 #ifdef TFU_UPGRADE
1908       rgSCHPwrGetDelta2FrmCqi(ueUl->validUlCqi, uePwr->trgCqi, ue, cell);
1909 #else
1910       rgSCHPwrGetDelta2FrmCqi(ueUl->crntUlCqi[0], uePwr->trgCqi, ue, cell);
1911 #endif
1912
1913    rgSCHPwrOnPuschPwrUpd(cell, ue);
1914 #ifdef TFU_UPGRADE
1915    if(uePwr->maxPwrDeltaByPhr < 0)
1916    {
1917       tmp = ueUl->validUlCqi;
1918       tmp = tmp + uePwr->maxPwrDeltaByPhr;
1919       if (tmp < 1 )
1920       {
1921          ueUl->validUlCqi = 1;
1922       }
1923       else
1924       {
1925          ueUl->validUlCqi = tmp;
1926       }
1927    }
1928 #endif 
1929
1930    return;
1931 }
1932
1933 /**
1934  * @brief Updates the stored last number of RBs allocated
1935  *
1936  * @details
1937  *
1938  *     Function : rgSCHPwrRecordRbAlloc
1939  *
1940  *     Invoking Module Processing:
1941  *      - This shall be invoked when uplink allocation is made for
1942  *        a UE.
1943  *      - Note: If outstanding TPCs are considered at the time
1944  *        of PHR report, the last numRb would also be known
1945  *        and then this API would not be needed. 
1946  *
1947  *     Processing Steps:
1948  *     - Adjust PHR according to now allocated number of RBs
1949  *     - Store the number of RBs
1950  *
1951  *  @param[in]  RgSchCellCb         *cell
1952  *  @param[in]  RgSchUeCb           *ue
1953  *  @param[in]  uint8_t                   numRb
1954  *  @return  Void
1955  **/
1956 Void rgSCHPwrRecordRbAlloc(RgSchCellCb *cell,RgSchUeCb  *ue,uint8_t  numRb)
1957 {
1958    RgSchCmnUeUlPwrCb     *uePwr   = RG_SCH_PWR_GETUEPWR(ue, cell);
1959    UNUSED(cell);
1960    return; 
1961
1962    if (uePwr->isPhrAvail)
1963    {
1964       uePwr->phVal += rgSCHPwrRbToPwr(cell,numRb) - rgSCHPwrRbToPwr(cell,uePwr->numRb);
1965       uePwr->phVal = RGSCH_MIN(40, uePwr->phVal);
1966    }
1967    uePwr->numRb = numRb;
1968    return;
1969 }
1970
1971 /**
1972  * @brief Handles power related configuration for a cell
1973  *
1974  * @details
1975  *
1976  *     Function : rgSCHPwrCellCfg
1977  *
1978  *     Invoking Module Processing:
1979  *      - This shall be invoked during cell config
1980  *        
1981  *     Processing Steps:
1982  *      - Set pMax
1983  *      - Set target CQI
1984  *      - Update TPC-RNTI information for the cell for Pucch and Pusch.
1985  *      - For each TPC-Pucch-RNTI,
1986  *         - Call  rgSCHAddRntiToPucchRntiLst()
1987  *      - For each TPC-Pusch-RNTI,
1988  *         - Call  rgSCHAddRntiToPuschRntiLst()
1989  *      - Return ROK
1990  *
1991  *  @param[in]  RgSchCellCb  *cell
1992  *  @param[in]  RgrCellCfg   *cfg
1993  *  @return  S16
1994  *      -# ROK
1995  *      -# RFAILED
1996  **/
1997 S16 rgSCHPwrCellCfg(RgSchCellCb *cell,RgrCellCfg  *cfg)
1998 {
1999    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2000    CmLteRnti              rnti;
2001    CmLteRnti              startRnti;
2002    uint16_t                    size;
2003    Bool                   isFmt3a;
2004
2005    /* Right now, all UEs have fixed maximum power capability. So
2006     * we store cell wide pMax as minimum of configured pMax and
2007     * UE's max power */
2008    cellPwr->pMax = RGSCH_MIN(cfg->pMax, RG_SCH_PWR_UE_MAX_PWR);
2009
2010    /* trgUlCqi already validated by common */
2011    cellPwr->trgUlCqi = cfg->trgUlCqi.trgCqi;
2012
2013    /* Validate number of TPC RNTIs */
2014    if ((cfg->pwrCfg.pucchPwrFmt3.size + cfg->pwrCfg.pucchPwrFmt3a.size
2015             > RG_SCH_CMN_MAX_NUM_TPC_PUCCH_RNTI)
2016          || (cfg->pwrCfg.puschPwrFmt3.size + cfg->pwrCfg.puschPwrFmt3a.size
2017             > RG_SCH_CMN_MAX_NUM_TPC_PUSCH_RNTI))
2018    {
2019       return RFAILED;
2020    }
2021
2022    /* Now initialise TPC RNTIs */
2023
2024    /* Format 3 Pucch TPC RNTIs */
2025    isFmt3a = FALSE;
2026    startRnti = cfg->pwrCfg.pucchPwrFmt3.startTpcRnti;
2027    size = cfg->pwrCfg.pucchPwrFmt3.size;
2028    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2029    {
2030       rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2031    }
2032
2033    /* Format 3A Pucch TPC RNTIs */
2034    isFmt3a = TRUE;
2035    startRnti = cfg->pwrCfg.pucchPwrFmt3a.startTpcRnti;
2036    size = cfg->pwrCfg.pucchPwrFmt3a.size;
2037    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2038    {
2039       rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2040    }
2041
2042    /* Format 3 Pusch TPC RNTIs */
2043    isFmt3a = FALSE;
2044    startRnti = cfg->pwrCfg.puschPwrFmt3.startTpcRnti;
2045    size = cfg->pwrCfg.puschPwrFmt3.size;
2046    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2047    {
2048       rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2049    }
2050
2051    /* Format 3A Pusch TPC RNTIs */
2052    isFmt3a = TRUE;
2053    startRnti = cfg->pwrCfg.puschPwrFmt3a.startTpcRnti;
2054    size = cfg->pwrCfg.puschPwrFmt3a.size;
2055    for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2056    {
2057       rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2058    }
2059
2060    return ROK;
2061 }
2062
2063 /**
2064  * @brief Handles power related re-configuration for a cell
2065  *
2066  * @details
2067  *
2068  *     Function : rgSCHPwrCellRecfg
2069  *
2070  *     Processing Steps:
2071  *     - NONE
2072  *
2073  *  @param[in]  RgSchCellCb  *cell
2074  *  @param[in]  RgrCellRecfg *recfg
2075  *  @return  S16
2076  *      -# ROK
2077  **/
2078 S16 rgSCHPwrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg)
2079 {
2080    UNUSED(cell);
2081    UNUSED(recfg);
2082
2083    /* Not doing anything for power reconfig, so such structure
2084     * in RGR */
2085    return ROK;
2086 }
2087
2088 /**
2089  * @brief Frees power related data structures in cell
2090  *
2091  * @details
2092  *
2093  *     Function : rgSCHPwrCellDel
2094  *
2095  *     Processing Steps:
2096  *      - NONE
2097  *
2098  *  @param[in]  RgSchCellCb  *cell
2099  *  @return  Void
2100  **/
2101 Void rgSCHPwrCellDel(RgSchCellCb *cell)
2102 {
2103    UNUSED(cell);
2104
2105    /* There is no allocated memory, so do nothing */
2106    return;
2107 }
2108
2109
2110 #ifdef LTE_ADV
2111 /**
2112  * @brief Configures ULPC CB for a SCELL being added
2113  *
2114  * @details
2115  *
2116  *     Function : rgSCHPwrUeSCellCfg
2117  *
2118  *  @param[in]  RgSchCellCb  *cell
2119  *  @param[in]  RgSchUeCb    *ue
2120  *  @param[in]  RgrUeCfg     *cfg
2121  *  @return  S16
2122  *      -# ROK
2123  *      -# RFAILED
2124  **/
2125 S16 rgSCHPwrUeSCellCfg(RgSchCellCb *cell,RgSchUeCb   *ue,RgrUeSecCellCfg  *sCellInfoCfg)
2126 {
2127    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2128    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2129    RgSchCmnUeUlPwrCb     *uePwrPCell = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2130    RgSchCmnUlUe          *ueUl        = RG_SCH_CMN_GET_UL_UE(ue, cell);
2131
2132    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
2133
2134
2135    uePwr->maxUePwr = cellPwr->pMax;
2136    uePwr->trgCqi   = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2137    uePwr->numRb    = 1;
2138
2139    uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2140
2141    uePwr->isPhrAvail  = FALSE;
2142    uePwr->phVal       = 40;
2143    uePwr->maxUlRbs    = RGSCH_MAX_DL_BW;
2144    uePwr->delta       = 0;
2145    uePwr->puschTpc    = 1;
2146    uePwr->remPuschPwr = 0;
2147
2148    /* Rest of the vars update and group power control related
2149     * config happens in the function below */
2150    uePwr->isAccumulated = sCellInfoCfg->ueSCellUlDedPwrCfg.isAccumulated;
2151    uePwr->deltaMcsEnbld = sCellInfoCfg->ueSCellUlDedPwrCfg.isDeltaMCSEnabled;
2152
2153    uePwr->trgCqi = uePwrPCell->trgCqi;
2154
2155    if (ueUl->maxUlCqi < uePwr->trgCqi)
2156    {
2157       uePwr->trgCqi = ueUl->maxUlCqi;
2158    }
2159    uePwr->p0UePusch = sCellInfoCfg->ueSCellUlDedPwrCfg.p0UePusch;
2160
2161    return ROK;
2162 }
2163 #endif
2164
2165 /**
2166  * @brief Handles power related configuration for a UE
2167  *
2168  * @details
2169  *
2170  *     Function : rgSCHPwrUeCfg
2171  *
2172  *     Processing Steps:
2173  *      - If Pusch group power configuration exists && accumulation enabled,
2174  *        - Fetch the TPC-Pusch-RNTI control block for the configured
2175  *        TPC-Pusch-RNTI. Call rgSCHGetRntiFrmPuschRntiLst(). If it does not
2176  *        exist, return RFAILED.
2177  *        - Add Ue to the ueLst of TPC-Pusch-RNTI control block.
2178  *        - Update tpcPuschRntiCb pointer in UE.
2179  *        - Update the puschIdx value.
2180  *      - If Pucch group power configuration exists && accumulation enabled,
2181  *        - Fetch the TPC-Pucch-RNTI control block for the configured
2182  *        TPC-Pucch-RNTI. Call rgSCHGetRntiFrmPucchRntiLst(). If it does not
2183  *        exist, return RFAILED.
2184  *        - Add Ue to the ueLst of TPC-Pucch-RNTI control block.
2185  *        - Update tpcPucchRntiCb pointer in UE.
2186  *        - Update the pucchIdx value.
2187  *      - Update isAccumulated and isDeltaMcs variables.
2188  *      - maxUlRbs = configured maximum UL bandwidth value per UE.
2189  *      - trgUlCqi = configured value, if any, else cell-wide default trg CQI value.
2190  *      - If format type is format 3A, update remaining power to +1
2191  *      - Update TPC-RNTI information for the cell for Pucch and Pusch.
2192  *      - Return ROK
2193  *
2194  *  @param[in]  RgSchCellCb  *cell
2195  *  @param[in]  RgSchUeCb    *ue
2196  *  @param[in]  RgrUeCfg     *cfg
2197  *  @return  S16
2198  *      -# ROK
2199  *      -# RFAILED
2200  **/
2201 S16 rgSCHPwrUeCfg(RgSchCellCb *cell,RgSchUeCb   *ue,RgrUeCfg    *cfg)
2202 {
2203    S16                    ret;
2204    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2205    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2206
2207    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
2208
2209    uePwr->maxUePwr = cellPwr->pMax;
2210    uePwr->trgCqi   = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2211    uePwr->numRb    = 1;
2212
2213    uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2214
2215    rgSCHPwrUeResetPucch(cell, ue);
2216    rgSCHPwrUeResetPusch(cell, ue);
2217
2218    /* Rest of the vars update and group power control related
2219     * config happens in the function below */
2220    ret = rgSCHPwrApplyUePwrCfg(cell, ue, &cfg->ueUlPwrCfg);
2221
2222    return (ret);
2223 }
2224
2225 /**
2226  * @brief Handles power related re-configuration for a UE
2227  *
2228  * @details
2229  *
2230  *     Function : rgSCHPwrUeRecfg
2231  *
2232  *     Invoking Module Processing:
2233  *      - This shall be invoked by SCH_GOM at UE re-configuration.
2234  *        
2235  *     Processing Steps:
2236  *      - If change in TPC-RNTI, update the pointer and the TPC RNTI Cb appropriately.
2237  *      - If accumulation disabled, remove the UE from TPC-RNTI lists of UE, if
2238  *      it exists.
2239  *      - If group power configuration disabled, remove the UE from TPC-RNTI lists of UE, if
2240  *      it exists.
2241  *
2242  *  @param[in]  RgSchCellCb  *cell
2243  *  @param[in]  RgSchUeCb    *ue
2244  *  @param[in]  RgrUeRecfg   *recfg
2245  *
2246  *  @return  S16
2247  *      -# ROK
2248  *      -# RFAILED
2249  **/
2250 S16 rgSCHPwrUeRecfg(RgSchCellCb   *cell,RgSchUeCb     *ue,RgrUeRecfg    *recfg)
2251 {
2252    S16                    ret;
2253    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2254    RgrUeUlPwrCfg         *pwrCfg = &recfg->ueUlPwrRecfg;
2255
2256    if (pwrCfg->p0UePucch != uePwr->p0UePucch)
2257    {
2258       rgSCHPwrUeResetPucch(cell, ue);
2259    }
2260    if ((pwrCfg->isAccumulated != uePwr->isAccumulated)
2261          || (pwrCfg->p0UePusch != uePwr->p0UePusch))
2262    {
2263       rgSCHPwrUeResetPusch(cell, ue);
2264    }
2265    ret = rgSCHPwrApplyUePwrCfg(cell, ue, &recfg->ueUlPwrRecfg);
2266
2267    return (ret);
2268 }
2269
2270 /***********************************************************
2271  *
2272  *     Func : rgSCHPwrApplyUePwrCfg
2273  *
2274  *     Desc : Applies power config for UE. Meants to be
2275  *            used during both power config and reconfig.
2276  *
2277  *     Ret  : ROK/RFAILED
2278  *
2279  *     Notes:
2280  *
2281  *     File :
2282  *
2283  **********************************************************/
2284 static S16 rgSCHPwrApplyUePwrCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeUlPwrCfg *pwrCfg)
2285 {
2286    S16                    ret;
2287    RgSchCmnUlUe          *ueUl        = RG_SCH_CMN_GET_UL_UE(ue, cell);
2288    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2289    RgSchCmnTpcRntiCb     *pucchRntiCb = NULLP;
2290    RgSchCmnTpcRntiCb     *puschRntiCb = NULLP;
2291    uint8_t               pucchIdx    = 0;
2292    uint8_t               puschIdx    = 0;
2293
2294    /* Validate Pucch group power control config */
2295    if (pwrCfg->uePucchPwr.pres)
2296    {
2297       pucchRntiCb =
2298          rgSCHPwrGetPucchRntiCb(cell, pwrCfg->uePucchPwr.tpcRnti);
2299       if (pucchRntiCb == NULLP)
2300       {
2301          return RFAILED;
2302       }
2303       pucchIdx = pwrCfg->uePucchPwr.idx;
2304       ret = rgSCHPwrChkPucchTpcRntiIdx(pucchRntiCb, pucchIdx);
2305       if (ret != ROK)
2306       {
2307          return (ret);
2308       }
2309    }
2310
2311    /* Validate Pusch group power control config */
2312    if (pwrCfg->uePuschPwr.pres)
2313    {
2314       puschRntiCb =
2315          rgSCHPwrGetPuschRntiCb(cell, pwrCfg->uePuschPwr.tpcRnti);
2316       if (puschRntiCb == NULLP)
2317       {
2318          return RFAILED;
2319       }
2320       puschIdx = pwrCfg->uePuschPwr.idx;
2321       ret = rgSCHPwrChkPuschTpcRntiIdx(puschRntiCb, puschIdx);
2322       if (ret != ROK)
2323       {
2324          return (ret);
2325       }
2326    }
2327
2328    /* Apply Pucch group power control config */
2329    if (pucchRntiCb)
2330    {
2331       if (uePwr->tpcPucchRntiCb != pucchRntiCb) /* This part for recfg */
2332       {
2333          if (uePwr->tpcPucchRntiCb)
2334          {
2335             rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2336          }
2337          uePwr->tpcPucchRntiCb = pucchRntiCb;
2338          rgSCHPwrAddUeToPucchTpcRntiCb(cell, pucchRntiCb, ue);
2339       }
2340       uePwr->pucchIdx = pucchIdx;
2341 #ifndef ALIGN_64BIT
2342        DU_LOG("\nDEBUG  -->  SCH : <GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2343                pucchRntiCb->cfgdUes.count,((uint32_t)pucchRntiCb->cfgdUes.first),
2344                ((uint32_t)pucchRntiCb->cfgdUes.last),ue->ueId);
2345        DU_LOG("\nDEBUG  -->  SCH : UEID:%d isFmt3a(%u) ueNode(%ld)",
2346                ue->ueId,pucchRntiCb->isFmt3a,
2347                pucchRntiCb->schdLnk.node);
2348        DU_LOG("\nDEBUG  -->  SCH : toBeSchdUes(%ld %lu %lu) tpcRnti(%u)", 
2349                pucchRntiCb->toBeSchdUes.count, 
2350                ((uint32_t)pucchRntiCb->toBeSchdUes.first),
2351                ((uint32_t)pucchRntiCb->toBeSchdUes.last), 
2352                pucchRntiCb->tpcRnti);
2353 #else
2354       DU_LOG("\nDEBUG  -->  SCH : <GRP_PWR>PucchRntiCb cfgdUes(%d %lu %lu) UEID:%d",
2355                pucchRntiCb->cfgdUes.count,((uint64_t)pucchRntiCb->cfgdUes.first),
2356                ((uint64_t)pucchRntiCb->cfgdUes.last),ue->ueId);
2357       DU_LOG("\nDEBUG  -->  SCH : UEID:%d isFmt3a(%u) ueNode(%ld)",
2358                ue->ueId,pucchRntiCb->isFmt3a,
2359                pucchRntiCb->schdLnk.node);
2360       DU_LOG("\nDEBUG  -->  SCH : toBeSchdUes(%d %lu %lu) tpcRnti(%u)", 
2361                pucchRntiCb->toBeSchdUes.count, 
2362                ((uint64_t)pucchRntiCb->toBeSchdUes.first),
2363                ((uint64_t)pucchRntiCb->toBeSchdUes.last), 
2364                pucchRntiCb->tpcRnti);
2365
2366 #endif
2367    }
2368
2369    /* Apply Pusch group power control config */
2370    if (puschRntiCb)
2371    {
2372       if (uePwr->tpcPuschRntiCb != puschRntiCb) /* This part for recfg */
2373       {
2374          if (uePwr->tpcPuschRntiCb)
2375          {
2376             rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2377          }
2378          uePwr->tpcPuschRntiCb = puschRntiCb;
2379          rgSCHPwrAddUeToPuschTpcRntiCb(puschRntiCb, ue);
2380       }
2381       uePwr->puschIdx = puschIdx;
2382    }
2383
2384    /* Update vars */
2385    uePwr->isAccumulated = pwrCfg->isAccumulated;
2386    uePwr->deltaMcsEnbld = pwrCfg->isDeltaMCSEnabled;
2387    if (pwrCfg->trgCqi)
2388    {
2389       uePwr->trgCqi = pwrCfg->trgCqi;
2390    }
2391    if (ueUl->maxUlCqi < uePwr->trgCqi)
2392    {
2393       uePwr->trgCqi = ueUl->maxUlCqi;
2394    }
2395    uePwr->p0UePusch = pwrCfg->p0UePusch;
2396    uePwr->p0UePucch = pwrCfg->p0UePucch;
2397
2398    return ROK;
2399 }
2400
2401
2402 /**
2403  * @brief Deletes power related information for UE
2404  *
2405  * @details
2406  *
2407  *     Function : rgSCHPwrUeDel
2408  *
2409  *     Invoking Module Processing:
2410  *      - This shall be invoked by at the time of UE deletion.
2411  *        
2412  *     Processing Steps:
2413  *     - if (ue->tpcPucchRntiCb)
2414  *       - delete UE from tpcPucchRntiCb->ueLst
2415  *       - ue->tpcPucchRntiCb = NULLP
2416  *       - If in (ue->tpcPucchRntiCb->toBeSchdLst) 
2417  *         - remove from the list.
2418  *     - if (ue->tpcPuschRntiCb)
2419  *       - delete UE from tpcPuschRntiCb->ueLst
2420  *       - ue->tpcPuschRntiCb = NULLP
2421  *       - If in (ue->tpcPuschRntiCb->toBeSchdLst) 
2422  *         - remove from the list.
2423  *
2424  *  @param[in]  RgSchCellCb     *cell
2425  *  @param[in]  RgSchUeCb       *ue
2426  *  @return  Void
2427  **/
2428 Void rgSCHPwrUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
2429 {
2430    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2431
2432    if (uePwr->tpcPucchRntiCb)
2433    {
2434       rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2435       uePwr->tpcPucchRntiCb = NULLP;
2436    }
2437    if (uePwr->tpcPuschRntiCb)
2438    {
2439       rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2440       uePwr->tpcPuschRntiCb = NULLP;
2441    }
2442    return;
2443 }
2444
2445 /**
2446  * @brief Resets UE's power state
2447  *
2448  * @details
2449  *
2450  *     Function : rgSCHPwrUeReset
2451  *
2452  *     Invoking Module Processing:
2453  *      - This shall be invoked by at the time PDCCH order.
2454  *
2455  *     Processing Steps:
2456  *     - Reset PUSCH power state
2457  *     - Reset PUCCH power state
2458  *
2459  *  @param[in]  RgSchCellCb     *cell
2460  *  @param[in]  RgSchUeCb       *ue
2461  *  @return  Void
2462  **/
2463 Void rgSCHPwrUeReset(RgSchCellCb  *cell,RgSchUeCb  *ue)
2464 {
2465
2466    rgSCHPwrUeResetPucch(cell, ue);
2467    rgSCHPwrUeResetPusch(cell, ue);
2468    return;
2469 }
2470
2471 /***********************************************************
2472  *
2473  *     Func : rgSCHPwrUeResetPucch
2474  *
2475  *     Desc : This function is called to reset UE
2476  *            to initial PUCCH power state.
2477  *
2478  *     Ret  : Void
2479  *
2480  *     Notes:
2481  *
2482  *     File :
2483  *
2484  **********************************************************/
2485 static Void rgSCHPwrUeResetPucch(RgSchCellCb *cell,RgSchUeCb *ue)
2486 {
2487    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2488
2489    uePwr->pucchTpc    = 1;
2490    uePwr->remPucchPwr = 0;
2491    if (uePwr->tpcPucchRntiCb)
2492    {
2493       rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2494    }
2495
2496    /* Stack Crash problem for TRACE5 changes. Added the line below */
2497   return;
2498  
2499 }
2500
2501 /***********************************************************
2502  *
2503  *     Func : rgSCHPwrUeResetPusch
2504  *
2505  *     Desc : This function is called to reset UE
2506  *            to initial PUSCH power state.
2507  *
2508  *     Ret  : Void
2509  *
2510  *     Notes:
2511  *
2512  *     File :
2513  *
2514  **********************************************************/
2515 static Void rgSCHPwrUeResetPusch(RgSchCellCb *cell,RgSchUeCb *ue)
2516 {
2517    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, cell);
2518
2519    uePwr->isPhrAvail  = FALSE;
2520    uePwr->phVal       = 40;
2521    uePwr->maxUlRbs    = RGSCH_MAX_DL_BW;
2522    uePwr->delta       = 0;
2523    uePwr->puschTpc    = 1;
2524    uePwr->remPuschPwr = 0;
2525    if (uePwr->tpcPuschRntiCb)
2526    {
2527       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2528    }
2529    return;
2530 }
2531
2532 /***********************************************************
2533  *
2534  *     Func : rgSCHPwrOnPuschPwrUpd
2535  *
2536  *     Desc : This function is called whenever 'remPuschPwr'
2537  *            is updated
2538  *
2539  *     Ret  : Void
2540  *
2541  *     Notes:
2542  *
2543  *     File :
2544  *
2545  **********************************************************/
2546 static Void rgSCHPwrOnPuschPwrUpd(RgSchCellCb  *cell,RgSchUeCb  *ue)
2547 {
2548    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2549    RgSchCmnTpcRntiCb     *cb;
2550    Bool                   toAdd;
2551
2552    if ((cb = uePwr->tpcPuschRntiCb) == NULLP)
2553    {
2554       return;
2555    }
2556
2557    /* Not checking for uwPwr->isPhrAvail as uePwr->phVal
2558     * is set to a large value initially */
2559    toAdd = FALSE;
2560
2561
2562    if ((uePwr->phVal != 0) && (uePwr->remPuschPwr != 0))
2563       {
2564          toAdd = TRUE;
2565       }
2566
2567
2568    if (toAdd)
2569    {
2570       rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue);
2571    }
2572    else
2573    {
2574       rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
2575    }
2576
2577    return;
2578 }
2579
2580
2581 /***********************************************************
2582  *
2583  *     Func : rgSCHPwrAddRntiToPucchRntiLst
2584  *
2585  *
2586  *     Desc : Adds RNTI to Pucch Rnti list and updates requisite
2587  *            information. 
2588  *
2589  *     Ret  : Void
2590  *
2591  *     Notes: Assumed that array bounds are checked
2592  *            in caller before adding.
2593  *
2594  *     File :
2595  *
2596  **********************************************************/
2597 static Void rgSCHPwrAddRntiToPucchRntiLst(RgSchCellCb *cell,CmLteRnti rnti,Bool  isFmt3a)
2598 {
2599    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2600
2601    rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPucchRntiLst[cellPwr->tpcPucchRntiCnt++],
2602        rnti, isFmt3a);
2603    return;
2604 }
2605
2606 /***********************************************************
2607  *
2608  *     Func : rgSCHPwrAddRntiToPuschRntiLst
2609  *
2610  *
2611  *     Desc : Adds RNTI to Pusch Rnti list and updates requisite
2612  *            information. 
2613  *
2614  *     Ret  : Void
2615  *
2616  *     Notes: Assumed that array bounds are checked
2617  *            in caller before adding.
2618  *
2619  *     File :
2620  *
2621  **********************************************************/
2622 static Void rgSCHPwrAddRntiToPuschRntiLst(RgSchCellCb *cell,CmLteRnti rnti,Bool  isFmt3a)
2623 {
2624    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2625
2626    rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPuschRntiLst[cellPwr->tpcPuschRntiCnt++], 
2627        rnti, isFmt3a);
2628    return;
2629 }
2630
2631 /***********************************************************
2632  *
2633  *     Func : rgSCHPwrInitTpcRntiCb
2634  *
2635  *
2636  *     Desc : Initialises a TPC RNTI CB
2637  *
2638  *     Ret  : Void
2639  *
2640  *     Notes:
2641  *
2642  *     File :
2643  *
2644  **********************************************************/
2645 static Void rgSCHPwrInitTpcRntiCb(RgSchCmnTpcRntiCb *cb,CmLteRnti rnti,Bool isFmt3a)
2646 {
2647
2648    memset(cb, 0, sizeof(*cb));
2649    cb->tpcRnti = rnti;
2650    cb->isFmt3a = isFmt3a;
2651    /* Not initialising lists as memset 0 takes care of it */
2652    /* cb->schdLnk.node is set when this rnti is to be scheduled */
2653    return;
2654 }
2655
2656 /***********************************************************
2657  *
2658  *     Func : rgSCHPwrGetPucchRntiCb
2659  *
2660  *
2661  *     Desc : Gets TPC RNTI control block from Pucch rnti list 
2662  *
2663  *     Ret  : RgSchCmnTpcRntiCb * - Success
2664  *            NULLP - Fail
2665  *
2666  *     Notes:
2667  *
2668  *     File :
2669  *
2670  **********************************************************/
2671 static RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb(RgSchCellCb *cell,CmLteRnti   tpcRnti)
2672 {
2673    RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2674    uint16_t  idx;
2675
2676    if (!cellPwr->tpcPucchRntiCnt)
2677    {
2678       return (NULLP);
2679    }
2680    for (idx = 0; idx < cellPwr->tpcPucchRntiCnt; ++idx)
2681    {
2682       if (cellPwr->tpcPucchRntiLst[idx].tpcRnti == tpcRnti)
2683       {
2684          return (&cellPwr->tpcPucchRntiLst[idx]);
2685       }
2686    }
2687    return (NULLP);
2688 }
2689
2690 /***********************************************************
2691  *
2692  *     Func : rgSCHPwrGetPuschRntiCb
2693  *
2694  *
2695  *     Desc : Gets TPC RNTI control block from Pusch rnti list 
2696  *
2697  *     Ret  : RgSchCmnTpcRntiCb * - Success
2698  *            NULLP - Fail
2699  *
2700  *     Notes:
2701  *
2702  *     File :
2703  *
2704  **********************************************************/
2705 static RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb(RgSchCellCb *cell,CmLteRnti   tpcRnti)
2706 {
2707    RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2708    uint16_t idx;
2709
2710    if (!cellPwr->tpcPuschRntiCnt)
2711    {
2712       return (NULLP);
2713    }
2714    for (idx = 0; idx < cellPwr->tpcPuschRntiCnt; ++idx)
2715    {
2716       if (cellPwr->tpcPuschRntiLst[idx].tpcRnti == tpcRnti)
2717       {
2718          return (&cellPwr->tpcPuschRntiLst[idx]);
2719       }
2720    }
2721    return (NULLP);
2722 }
2723
2724
2725 /***********************************************************
2726  *
2727  *     Func : rgSCHPwrAddUeToPucchTpcRntiCb
2728  *
2729  *
2730  *     Desc : Add UE to cfgd list of UEs in rnti cb
2731  *
2732  *     Ret  :
2733  *
2734  *     Notes:
2735  *
2736  *     File :
2737  *
2738  **********************************************************/
2739 static Void rgSCHPwrAddUeToPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb *ue)
2740 {
2741    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2742    UNUSED(cell);
2743
2744    cmLListAdd2Tail(&cb->cfgdUes, &uePwr->pucchGrpLnk);
2745    uePwr->pucchGrpLnk.node = (PTR)ue;
2746    return;
2747 }
2748
2749 /***********************************************************
2750  *
2751  *     Func : rgSCHPwrDelUeFrmPucchTpcRntiCb
2752  *
2753  *
2754  *     Desc : Remove UE from Pucch TPC RNTI CB
2755  *
2756  *     Ret  :
2757  *
2758  *     Notes:
2759  *
2760  *     File :
2761  *
2762  **********************************************************/
2763 static Void rgSCHPwrDelUeFrmPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb  *ue)
2764 {
2765    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2766
2767    rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
2768    cmLListDelFrm(&cb->cfgdUes, &uePwr->pucchGrpLnk);
2769    uePwr->pucchGrpLnk.node = NULLP;
2770    return;
2771 }
2772
2773 /***********************************************************
2774  *
2775  *     Func : rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
2776  *
2777  *
2778  *     Desc : Remove UE from to-be-scheduled list of UEs
2779  *            in Pusch RNTI CB
2780  *
2781  *     Ret  :
2782  *
2783  *     Notes:
2784  *
2785  *     File :
2786  *
2787  **********************************************************/
2788 static Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb  *cb,RgSchUeCb *ue)
2789 {
2790    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2791
2792    if (uePwr->schdPucchGrpLnk.node == NULLP)
2793    {
2794       return;
2795    }
2796    rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue);
2797    if (!cb->toBeSchdUes.count)
2798    {
2799       rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
2800    }
2801    return;
2802 }
2803
2804 /***********************************************************
2805  *
2806  *     Func : rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
2807  *
2808  *     Desc : Remove UE from to-be-scheduled list of UEs
2809  *            in Pucch RNTI CB. Do not both about
2810  *            possibly removing Pucch RNTI CB from
2811  *            the cell wide to-be-scheduled list.
2812  *
2813  *     Ret  :
2814  *
2815  *     Notes:
2816  *
2817  *     File :
2818  *
2819  **********************************************************/
2820 static Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb  *cb,RgSchUeCb *ue)
2821 {
2822    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2823
2824    if (uePwr->schdPucchGrpLnk.node != NULLP)
2825    {
2826       cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
2827       uePwr->schdPucchGrpLnk.node = NULLP;
2828    }
2829    return;
2830 }
2831
2832 /***********************************************************
2833  *
2834  *     Func : rgSCHPwrRmvSchdPucchTpcRntiCb
2835  *
2836  *     Desc : Remove Pucch TPC RNTI CB from to-be-scheduled
2837  *            list in cell
2838  *
2839  *     Ret  : Void
2840  *
2841  *     Notes:
2842  *
2843  *     File :
2844  *
2845  **********************************************************/
2846 static Void rgSCHPwrRmvSchdPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb)
2847 {
2848    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2849
2850    if (cb->schdLnk.node == NULLP)
2851    {
2852       return;
2853    }
2854    cmLListDelFrm(&cellPwr->pucchGrpPwr, &cb->schdLnk);
2855    cb->schdLnk.node = NULLP;
2856    return;
2857 }
2858
2859 /***********************************************************
2860  *
2861  *     Func : rgSCHPwrAddSchdUeToPucchTpcRntiCb
2862  *
2863  *     Desc : Add UE to to-be-scheduled list of UEs
2864  *            in Pucch RNTI CB
2865  *
2866  *     Ret  :
2867  *
2868  *     Notes:
2869  *
2870  *     File :
2871  *
2872  **********************************************************/
2873 static Void rgSCHPwrAddSchdUeToPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb *ue)
2874 {
2875    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2876
2877    if (uePwr->schdPucchGrpLnk.node != NULLP)
2878    {
2879       /* UE is already in the list */
2880       return;
2881    }
2882    cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
2883    uePwr->schdPucchGrpLnk.node = (PTR)ue;
2884    if (cb->toBeSchdUes.count == 1)
2885    {
2886       /* This is first UE, so queue up this TPC RNTI
2887        * for scheduling */
2888       rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb);
2889    }
2890    return;
2891 }
2892
2893 /***********************************************************
2894  *
2895  *     Func : rgSCHPwrAddSchdPucchTpcRntiCb
2896  *
2897  *     Desc : Add Pucch TPC RNTI CB from to-be-scheduled
2898  *            list in cell
2899  *
2900  *     Ret  : Void
2901  *
2902  *     Notes:
2903  *
2904  *     File :
2905  *
2906  **********************************************************/
2907 static Void rgSCHPwrAddSchdPucchTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb)
2908 {
2909    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2910
2911    cmLListAdd2Tail(&cellPwr->pucchGrpPwr, &cb->schdLnk);
2912    cb->schdLnk.node = (PTR)cb;
2913    return;
2914 }
2915
2916
2917 /***********************************************************
2918  *
2919  *     Func : rgSCHPwrAddUeToPuschTpcRntiCb
2920  *
2921  *
2922  *     Desc : Add UE to cfgd list of UEs in rnti cb
2923  *
2924  *     Ret  :
2925  *
2926  *     Notes:
2927  *
2928  *     File :
2929  *
2930  **********************************************************/
2931 static Void rgSCHPwrAddUeToPuschTpcRntiCb(RgSchCmnTpcRntiCb *cb,RgSchUeCb  *ue)
2932 {
2933    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2934
2935    cmLListAdd2Tail(&cb->cfgdUes, &uePwr->puschGrpLnk);
2936    uePwr->puschGrpLnk.node = (PTR)ue;
2937    return;
2938 }
2939
2940 /***********************************************************
2941  *
2942  *     Func : rgSCHPwrAddSchdUeToPuschTpcRntiCb
2943  *
2944  *     Desc : Add UE to to-be-scheduled list of UEs
2945  *            in Pusch RNTI CB
2946  *
2947  *     Ret  :
2948  *
2949  *     Notes:
2950  *
2951  *     File :
2952  *
2953  **********************************************************/
2954 static Void rgSCHPwrAddSchdUeToPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb *ue)
2955 {
2956    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2957
2958    if (uePwr->schdPuschGrpLnk.node != NULLP)
2959    {
2960       /* UE is already in the list */
2961       return;
2962    }
2963    cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
2964    uePwr->schdPuschGrpLnk.node = (PTR)ue;
2965    if (cb->toBeSchdUes.count == 1)
2966    {
2967       /* This is first UE, so queue up this TPC RNTI
2968        * for scheduling */
2969       rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb);
2970    }
2971    return;
2972 }
2973
2974 /***********************************************************
2975  *
2976  *     Func : rgSCHPwrDelUeFrmPuschTpcRntiCb
2977  *
2978  *
2979  *     Desc : Add UE to cfgd list of UEs in rnti cb
2980  *
2981  *     Ret  :
2982  *
2983  *     Notes:
2984  *
2985  *     File :
2986  *
2987  **********************************************************/
2988 static Void rgSCHPwrDelUeFrmPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb  *cb,RgSchUeCb  *ue)
2989 {
2990    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2991
2992    rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
2993    cmLListDelFrm(&cb->cfgdUes, &uePwr->puschGrpLnk);
2994    uePwr->puschGrpLnk.node = NULLP;
2995    return;
2996 }
2997
2998 /***********************************************************
2999  *
3000  *     Func : rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3001  *
3002  *     Desc : Remove UE from to-be-scheduled list of UEs
3003  *            in Pusch RNTI CB
3004  *
3005  *     Ret  :
3006  *
3007  *     Notes:
3008  *
3009  *     File :
3010  *
3011  **********************************************************/
3012 static Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb *ue)
3013 {
3014    RgSchCmnUeUlPwrCb     *uePwr       = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3015
3016    if (uePwr->schdPuschGrpLnk.node == NULLP)
3017    {
3018       return;
3019    }
3020    rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue);
3021    if (!cb->toBeSchdUes.count)
3022    {
3023       rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
3024    }
3025    return;
3026 }
3027
3028 /***********************************************************
3029  *
3030  *     Func : rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3031  *
3032  *     Desc : Remove UE from to-be-scheduled list of UEs
3033  *            in Pusch RNTI CB. Do not both about
3034  *            possibly removing Pusch RNTI CB from
3035  *            the cell wide to-be-scheduled list.
3036  *
3037  *     Ret  :
3038  *
3039  *     Notes:
3040  *
3041  *     File :
3042  *
3043  **********************************************************/
3044 static Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb,RgSchUeCb *ue)
3045 {
3046    RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3047
3048    if (uePwr->schdPuschGrpLnk.node != NULLP)
3049    {
3050       cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3051       uePwr->schdPuschGrpLnk.node = NULLP;
3052    }
3053    return;
3054 }
3055
3056 /***********************************************************
3057  *
3058  *     Func : rgSCHPwrAddSchdPuschTpcRntiCb
3059  *
3060  *     Desc : Add Pusch TPC RNTI CB from to-be-scheduled
3061  *            list in cell
3062  *
3063  *     Ret  : Void
3064  *
3065  *     Notes:
3066  *
3067  *     File :
3068  *
3069  **********************************************************/
3070 static Void rgSCHPwrAddSchdPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb)
3071 {
3072    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3073
3074    cmLListAdd2Tail(&cellPwr->puschGrpPwr, &cb->schdLnk);
3075    cb->schdLnk.node = (PTR)cb;
3076    return;
3077 }
3078
3079 /***********************************************************
3080  *
3081  *     Func : rgSCHPwrRmvSchdPuschTpcRntiCb
3082  *
3083  *     Desc : Remove Pusch TPC RNTI CB from to-be-scheduled
3084  *            list in cell
3085  *
3086  *     Ret  : Void
3087  *
3088  *     Notes:
3089  *
3090  *     File :
3091  *
3092  **********************************************************/
3093 static Void rgSCHPwrRmvSchdPuschTpcRntiCb(RgSchCellCb *cell,RgSchCmnTpcRntiCb *cb)
3094 {
3095    RgSchCmnUlPwrCb       *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3096
3097    if (cb->schdLnk.node == NULLP)
3098    {
3099       return;
3100    }
3101    cmLListDelFrm(&cellPwr->puschGrpPwr, &cb->schdLnk);
3102    cb->schdLnk.node = NULLP;
3103    return;
3104 }
3105
3106 /***********************************************************
3107  *
3108  *     Func : rgSCHPwrChkPucchTpcRntiIdx
3109  *
3110  *     Desc : Validate that the given index is OK to
3111  *            be assigned to a new UE for the Pucch TPC
3112  *            RNTI
3113  *
3114  *     Ret  :
3115  *
3116  *     Notes:
3117  *
3118  *     File :
3119  *
3120  **********************************************************/
3121 static S16 rgSCHPwrChkPucchTpcRntiIdx(RgSchCmnTpcRntiCb *cb,uint8_t idx)
3122 {
3123
3124    if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3125    {
3126       return RFAILED;
3127    }
3128    if (rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx) != ROK)
3129    {
3130       return RFAILED;
3131    }
3132    return ROK;
3133 }
3134
3135 /***********************************************************
3136  *
3137  *     Func : rgSCHPwrChkPuschTpcRntiIdx
3138  *
3139  *     Desc : Validate that the given index is OK to
3140  *            be assigned to a new UE for the Pusch TPC
3141  *            RNTI
3142  *
3143  *     Ret  :
3144  *
3145  *     Notes:
3146  *
3147  *     File :
3148  *
3149  **********************************************************/
3150 static S16 rgSCHPwrChkPuschTpcRntiIdx(RgSchCmnTpcRntiCb *cb,uint8_t  idx)
3151 {
3152
3153    if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3154    {
3155       return RFAILED;
3156    }
3157    if (rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx) != ROK)
3158    {
3159       return RFAILED;
3160    }
3161    return ROK;
3162 }
3163
3164 /***********************************************************
3165  *
3166  *     Func : rgSCHPwrChkUniqPucchTpcRntiIdx
3167  *
3168  *     Desc : Validate index against format type of TPC RNTI
3169  *
3170  *     Ret  :
3171  *
3172  *     Notes:
3173  *
3174  *     File :
3175  *
3176  **********************************************************/
3177 static S16 rgSCHPwrChkUniqPucchTpcRntiIdx(RgSchCmnTpcRntiCb *cb,uint8_t idx)
3178 {
3179    CmLList           *lnk;
3180
3181    for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
3182    {
3183       RgSchUeCb             *ue = (RgSchUeCb *)lnk->node;
3184       RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3185       if (uePwr->pucchIdx == idx)
3186       {
3187          return RFAILED;
3188       }
3189    }
3190    return ROK;
3191 }
3192
3193 /***********************************************************
3194  *
3195  *     Func : rgSCHPwrChkUniqPuschTpcRntiIdx
3196  *
3197  *     Desc : Validate index against format type of TPC RNTI
3198  *
3199  *     Ret  :
3200  *
3201  *     Notes:
3202  *
3203  *     File :
3204  *
3205  **********************************************************/
3206 static S16 rgSCHPwrChkUniqPuschTpcRntiIdx(RgSchCmnTpcRntiCb  *cb,uint8_t  idx)
3207 {
3208    CmLList           *lnk;
3209
3210    for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
3211    {
3212       RgSchUeCb             *ue = (RgSchUeCb *)lnk->node;
3213       RgSchCmnUeUlPwrCb     *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3214       if (uePwr->puschIdx == idx)
3215       {
3216          return RFAILED;
3217       }
3218    }
3219    return ROK;
3220 }
3221
3222 /***********************************************************
3223  *
3224  *     Func : rgSCHPwrChkTpcRntiIdx
3225  *
3226  *     Desc : Validate index against format type of TPC RNTI.
3227  *
3228  *     Ret  :
3229  *
3230  *     Notes:
3231  *
3232  *     File :
3233  *
3234  **********************************************************/
3235 static S16 rgSCHPwrChkTpcRntiIdx(RgSchCmnTpcRntiCb *cb,uint8_t idx)
3236 {
3237    if (cb->isFmt3a)
3238    {
3239       if (idx >= TFU_MAX_1BIT_TPC)
3240       {
3241          return RFAILED;
3242       }
3243    }
3244    else
3245    {
3246       if (idx >= TFU_MAX_2BIT_TPC)
3247       {
3248          return RFAILED;
3249       }
3250    }
3251    return ROK;
3252 }
3253 /* Warning Fix: Commenting out as not used */
3254
3255 /***********************************************************
3256  *
3257  *     Func : rgSCHPwrGetPCMaxValFromPCMax
3258  *
3259  *     Desc : Returns the power headroom in dB
3260  *            corresponding to a power headroom
3261  *            report
3262  *
3263  *     Ret  : S8
3264  *
3265  *     Notes:
3266  *
3267  *     File :
3268  *
3269  **********************************************************/
3270 static S8 rgSCHPwrGetPCMaxValFromPCMax(uint8_t pCMax)
3271 {
3272    return ((pCMax & 63) - 30);
3273 }
3274
3275
3276
3277 /***********************************************************
3278  *
3279  *     Func : rgSCHPwrGetPhValFromPhr
3280  *
3281  *     Desc : Returns the power headroom in dB
3282  *            corresponding to a power headroom
3283  *            report
3284  *
3285  *     Ret  : S8
3286  *
3287  *     Notes:
3288  *
3289  *     File :
3290  *
3291  **********************************************************/
3292 static S8 rgSCHPwrGetPhValFromPhr(uint8_t  phr)
3293 {
3294    return ((phr & 63) - 23);
3295 }
3296
3297
3298 \f
3299 /**********************************************************************
3300  
3301          End of file
3302 **********************************************************************/