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