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