1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for power control functionality
29 **********************************************************************/
31 /** @file rg_sch_pwr.c
32 @brief This module handles schedulers' power control functionality
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 "envopt.h" /* environment options */
40 #include "envdep.h" /* environment dependent */
41 #include "envind.h" /* environment independent */
42 #include "gen.h" /* general layer */
43 #include "ssi.h" /* system service interface */
44 #include "cm_hash.h" /* common hash list */
45 #include "cm_llist.h" /* common linked list library */
46 #include "cm_err.h" /* common error */
47 #include "cm_lte.h" /* common LTE */
48 #include "cm_math.h" /* common MATH functions */
54 #include "rg_sch_inf.h"
55 #include "rg_sch_err.h"
57 #include "rg_sch_cmn.h"
59 /* header/extern include files (.x) */
60 #include "gen.x" /* general layer typedefs */
61 #include "ssi.x" /* system services typedefs */
62 #include "cm5.x" /* common timers */
63 #include "cm_hash.x" /* common hash list */
64 #include "cm_lib.x" /* common library */
65 #include "cm_llist.x" /* common linked list */
66 #include "cm_mblk.x" /* memory management */
67 #include "cm_tkns.x" /* common tokens */
68 #include "cm_lte.x" /* common tokens */
69 #include "cm_math.x" /* common MATH functions */
70 #include "tfu.x" /* RGU types */
71 #include "lrg.x" /* layer management typedefs for MAC */
72 #include "rgr.x" /* layer management typedefs for MAC */
73 #include "rgm.x" /* layer management typedefs for MAC */
74 #include "rg_sch_inf.x" /* typedefs for Scheduler */
75 #include "rg_sch.x" /* typedefs for Scheduler */
76 #include "rg_sch_cmn.x"
77 #include "rl_interface.h"
78 #include "rl_common.h"
81 /* Current specs have 23 dBm as max tx power capability for UEs */
82 #define RG_SCH_PWR_UE_MAX_PWR 23
84 #define RG_SCH_REF_PCMAX 0xFF
86 #define RG_SCH_CMN_GET_UL_UE(_ue,_cell) (&(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
87 [RG_SCH_CELLINDEX(_cell)]])->sch))->ul))
88 #define RG_SCH_PWR_GETUEPWR(_ue, _cell) &(((RgSchCmnUe *)((_ue->cellInfo[_ue->cellIdToCellIdxMap\
89 [RG_SCH_CELLINDEX(_cell)]])->sch))->ul.ulPwrCb)
90 #define RG_SCH_PWR_GETCELLPWR(cell) &((RgSchCmnCell *)((cell)->sc.sch))->ul.ulPwrCb
93 typedef S8 RgSchCmnUlPwrCqiToPwrTbl[RG_SCH_CMN_UL_NUM_CQI];
95 PRIVATE RgSchCmnUlPwrCqiToPwrTbl rgSchPwrCqiToPwrTbl;
97 /* This table maps a given number of RBs (given by array index)
98 * to the power in dB that these many RBs map to. */
99 CONSTANT U8 rgSchPwrRbToPwrTbl[111] = { 0, /* First entry is dummy */
100 0, 3, 4, 6, 7, 7, 8, 9, 9, 10,
101 10, 10, 11, 11, 11, 12, 12, 12, 12, 13,
102 13, 13, 13, 13, 14, 14, 14, 14, 14, 14,
103 15, 15, 15, 15, 15, 15, 15, 15, 16, 16,
104 16, 16, 16, 16, 16, 16, 16, 16, 17, 17,
105 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
106 17, 18, 18, 18, 18, 18, 18, 18, 18, 18,
107 18, 18, 18, 18, 18, 18, 18, 19, 19, 19,
108 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
109 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
110 20, 20, 20, 20, 20, 20, 20, 20, 20, 20
114 /* This table maps power (in dB) to number of RBs */
115 /* The array size comes from max power in rgSchPwrRbToPwrTbl */
116 CONSTANT U8 rgSchPwrToRbTbl[20+1] = {
117 1, 1, 2, 2, 3, 4, 5, 6, 7, 9, 11,
118 13, 17, 21, 26, 33, 41, 52, 65, 82, 103
123 PRIVATE S8 rgSCHPwrGetCqiPwr ARGS((
126 PRIVATE S8 rgSCHPwrGetCqiPwrForUe ARGS((
131 PRIVATE S8 rgSCHPwrCalcEfficncyPwr ARGS((
134 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi ARGS((
140 PRIVATE Void rgSCHPwrGetPuschTpc ARGS((
147 PRIVATE U8 rgSCHPwrGetMaxRb ARGS((
151 PRIVATE U8 rgSCHPwrRbToPwr ARGS((
155 PRIVATE Void rgSCHPwrSchedPucchRnti ARGS((
157 RgSchCmnTpcRntiCb *cb,
162 PRIVATE Void rgSCHPwrPuschCntrl ARGS((
166 PRIVATE Void rgSCHPwrPucchCntrl ARGS((
170 PRIVATE Void rgSCHPwrSchedPuschRnti ARGS((
172 RgSchCmnTpcRntiCb *cb,
177 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe ARGS((
182 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe ARGS((
187 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe ARGS((
192 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe ARGS((
197 PRIVATE Void rgSCHPwrGetAcc1bitTpc ARGS((
202 PRIVATE Void rgSCHPwrGetAcc2bitTpc ARGS((
207 PRIVATE Void rgSCHPwrGetAbsTpc ARGS((
212 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe ARGS((
217 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe ARGS((
222 PRIVATE Bool rgSCHPwrIsDlUeSched ARGS((
227 PRIVATE Bool rgSCHPwrIsUlUeSched ARGS((
232 PRIVATE Void rgSCHPwrOnSchedPucchTpc ARGS((
237 PRIVATE Void rgSCHPwrOnSchedPuschTpc ARGS((
241 PRIVATE S16 rgSCHPwrApplyUePwrCfg ARGS((
244 RgrUeUlPwrCfg *pwrCfg
246 PRIVATE Void rgSCHPwrUeResetPucch ARGS((
250 PRIVATE Void rgSCHPwrUeResetPusch ARGS((
254 PRIVATE Void rgSCHPwrOnPuschPwrUpd ARGS((
258 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst ARGS((
263 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst ARGS((
268 PRIVATE Void rgSCHPwrInitTpcRntiCb ARGS((
269 RgSchCmnTpcRntiCb *cb,
273 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb ARGS((
277 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb ARGS((
281 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb ARGS((
283 RgSchCmnTpcRntiCb *cb,
286 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb ARGS((
288 RgSchCmnTpcRntiCb *cb,
291 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb ARGS((
293 RgSchCmnTpcRntiCb *cb,
296 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb ARGS((
298 RgSchCmnTpcRntiCb *cb,
301 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb ARGS((
303 RgSchCmnTpcRntiCb *cb
305 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb ARGS((
307 RgSchCmnTpcRntiCb *cb,
310 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb ARGS((
312 RgSchCmnTpcRntiCb *cb
314 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb ARGS((
315 RgSchCmnTpcRntiCb *cb,
318 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb ARGS((
320 RgSchCmnTpcRntiCb *cb,
323 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb ARGS((
325 RgSchCmnTpcRntiCb *cb,
328 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb ARGS((
330 RgSchCmnTpcRntiCb *cb,
333 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb ARGS((
335 RgSchCmnTpcRntiCb *cb,
338 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb ARGS((
340 RgSchCmnTpcRntiCb *cb
342 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb ARGS((
344 RgSchCmnTpcRntiCb *cb
346 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx ARGS((
347 RgSchCmnTpcRntiCb *cb,
350 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx ARGS((
351 RgSchCmnTpcRntiCb *cb,
354 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx ARGS((
355 RgSchCmnTpcRntiCb *cb,
358 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx ARGS((
359 RgSchCmnTpcRntiCb *cb,
362 PRIVATE S16 rgSCHPwrChkTpcRntiIdx ARGS((
363 RgSchCmnTpcRntiCb *cb,
366 PRIVATE S8 rgSCHPwrGetPhValFromPhr ARGS((
369 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax ARGS((
377 * @brief Does power related initialisation (not cell specific).
382 * Function : rgSCHPwrInit
385 * - This shall precompute coding efficiency to power
386 * mappings (assuming beta of 1).
391 PUBLIC Void rgSCHPwrInit
396 PUBLIC Void rgSCHPwrInit()
402 rgSchPwrCqiToPwrTbl[0] = 0; /* This should never be used anyway */
403 for (idx = 1; idx < RG_SCH_CMN_UL_NUM_CQI; ++idx)
405 rgSchPwrCqiToPwrTbl[idx] = rgSCHPwrCalcEfficncyPwr(rgSchCmnUlCqiTbl[idx].eff);
410 /***********************************************************
412 * Func : rgSCHPwrGetCqiPwr
414 * Desc : Returns power corresponding to coding efficiency
415 * when beta pusch is assumed 1.
423 **********************************************************/
425 PRIVATE S8 rgSCHPwrGetCqiPwr
430 PRIVATE S8 rgSCHPwrGetCqiPwr(cqi)
434 TRC2(rgSCHPwrGetCqiPwr);
436 RETVALUE(rgSchPwrCqiToPwrTbl[cqi]);
437 } /* rgSCHPwrGetCqiPwr */
439 /***********************************************************
441 * Func : rgSCHPwrGetCqiPwrForUe
443 * Desc : If MCS control is enabled for UE, returns
444 * power corresponding to CQI, else 0.
452 **********************************************************/
454 PRIVATE S8 rgSCHPwrGetCqiPwrForUe
461 PRIVATE S8 rgSCHPwrGetCqiPwrForUe(cell, ue, cqi)
467 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
468 TRC2(rgSCHPwrGetCqiPwrForUe);
470 if (!uePwr->deltaMcsEnbld)
474 RETVALUE(rgSCHPwrGetCqiPwr(cqi));
475 } /* rgSCHPwrGetCqiPwrForUe */
477 /***********************************************************
479 * Func : rgSCHPwrCalcEfficncyPwr
481 * Desc : Computes power corresponding to a coding
486 * Notes: Assumes beta pusch to be 1
490 **********************************************************/
492 PRIVATE S8 rgSCHPwrCalcEfficncyPwr
497 PRIVATE S8 rgSCHPwrCalcEfficncyPwr(eff)
501 F64 ks = 1.25; /* or F64 */
502 F64 tmp = cmPow(2, ks*eff/1024) - 1;
503 TRC2(rgSCHPwrCalcEfficncyPwr);
507 RETVALUE((S8)(10 * cmLog10(tmp)));
508 } /* rgSCHPwrCalcEfficncyPwr */
512 * @brief Returns TPC to be sent in UL allocation
516 * Function : rgSCHPwrPuschTpcForUe
518 * Invoking Module Processing:
519 * - After allocation for UE, this function shall
520 * be invoked to retrieve TPC.
521 * - This assumes that rgSCHPwrGetMaxUlRb() was
522 * invoked prior to final allocation for UE.
525 * - Just return TPC that was determined
527 * - After this, do necessary updates.
529 * @param[in] RgSchCellCb *cell
530 * @param[in] RgSchUeCb *ue
534 PUBLIC U8 rgSCHPwrPuschTpcForUe
540 PUBLIC U8 rgSCHPwrPuschTpcForUe(cell, ue)
545 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue,cell);
548 TRC2(rgSCHPwrPuschTpcForUe);
550 rgSCHPwrOnSchedPuschTpc(cell, ue);
551 RETVALUE(uePwr->puschTpc);
555 * @brief Handles Pusch power control for DCI format 0
559 * Function : rgSCHPwrGetMaxUlRb
561 * Invoking Module Processing:
562 * - This shall be invoked to determine maximum
563 * number of UL RBs for scheduling.
564 * - This is expected to be invoked every time
565 * priority to attempt at UE allocation. Later
566 * TPC retrieval depends on it.
569 * - Returns maximum allowed UL RBs to be granted
570 * after invoking Pusch power control.
572 * @param[in] RgSchCellCb *cell
573 * @param[in] RgSchUeCb *ue
577 PUBLIC U8 rgSCHPwrGetMaxUlRb
583 PUBLIC U8 rgSCHPwrGetMaxUlRb(cell, ue)
588 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
589 TRC2(rgSCHPwrGetMaxUlRb);
591 rgSCHPwrPuschCntrl(cell, ue); /* This stores tpc, delta and maxRb
593 RETVALUE(uePwr->maxUlRbs);
597 * @brief Handles Pusch power control for DCI format 0
601 * Function : rgSCHPwrPuschCntrl
603 * Invoking Module Processing:
604 * - This shall be invoked to determine TPC
605 * and maximum number of UL RBs for scheduling
606 * (through DCI format 0).
609 * - 'remPuschPwr' is the final delta power that the UE
610 * should apply to get to target CQI.
611 * - The available headroom (availPwr) is determined.
612 * - Power command is given by considering remPuschPwr and
614 * - After factoring in the power command into availPwr, the
615 * maximum number of RBs that can be supported is determined
616 * assuming that UE is going to use transmission efficiency
617 * corresponding to current CQI.
618 * - The results determined in this function are stored
619 * in the UE power control block.
620 * - [Not doing anything of power control of msg3
621 * retransmissions now]
623 * @param[in] RgSchCellCb *cell
624 * @param[in] RgSchUeCb *ue
628 PRIVATE Void rgSCHPwrPuschCntrl
634 PRIVATE Void rgSCHPwrPuschCntrl(cell, ue)
639 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
640 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
641 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
644 U8 cqi = ueUl->validUlCqi;
647 U8 cqi = ueUl->crntUlCqi[0];
649 Bool isAcc = uePwr->isAccumulated;
656 TRC2(rgSCHPwrPuschCntrl);
658 if (!uePwr->isPhrAvail)
660 availPwr = 60; /* setting a large value so that availPwr does
661 * not constrain delta */
665 availPwr = uePwr->maxUePwr - uePwr->pwrPerRb;
666 availPwr -= rgSCHPwrGetCqiPwrForUe(cell, ue, cqi);
668 delta = uePwr->remPuschPwr;
669 rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, &tpc, &delta);
672 maxRb = rgSCHPwrGetMaxRb(cell,availPwr);
674 /* Store the results in ue power control block to be used later */
675 if(maxRb < cellUl->sbSize)
677 maxRb = cellUl->sbSize;
679 if(uePwr->maxPwrDeltaByPhr < 0)
681 tmp = ueUl->validUlCqi;
682 tmp = tmp + uePwr->maxPwrDeltaByPhr;
685 ueUl->validUlCqi = 1;
689 ueUl->validUlCqi = tmp;
694 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
695 "UEID:%d Output Max Rb (%d), phVal (%d) AvailPwr (%d) ",
696 ue->ueId, maxRb, uePwr->phVal, availPwr);
697 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
698 "UEID:%d pwrPerRb %d remPuschPwr %d",
702 uePwr->delta = delta;
703 uePwr->maxUlRbs = maxRb;
704 uePwr->puschTpc = tpc;
709 * @brief Returns TPC to be sent in DL allocation
713 * Function : rgSCHPwrPucchTpcForUe
715 * Invoking Module Processing:
716 * - After DL allocation for UE, this function shall
717 * be invoked to obtain TPC.
720 * - Do Pucch power control processing
723 * @param[in] RgSchCellCb *cell
724 * @param[in] RgSchUeCb *ue
728 PUBLIC U8 rgSCHPwrPucchTpcForUe
734 PUBLIC U8 rgSCHPwrPucchTpcForUe(cell, ue)
739 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
740 TRC2(rgSCHPwrPucchTpcForUe);
742 rgSCHPwrPucchCntrl(cell, ue);
743 RETVALUE(uePwr->pucchTpc);
746 /***********************************************************
748 * Func : rgSCHPwrGetDelta2FrmCqi
750 * Desc : Get power to be applied to achieve
751 * target CQI (the power returned is
752 * twice is actual power)
760 **********************************************************/
762 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi
771 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi(crntCqi, trgCqi)
778 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
779 TRC2(rgSCHPwrGetDelta2FrmCqi);
781 if (uePwr->isPhrAvail)
783 //uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb - uePwr->remPuschPwr;
784 uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb;
788 uePwr->maxPwrDeltaByPhr = 0;
791 if (uePwr->maxPwrDeltaByPhr < 0 && (trgCqi - crntCqi) *
792 RG_SCH_UL_CQI_DB_STEP_2 > 0)
796 RETVALUE(RGSCH_MIN(uePwr->maxPwrDeltaByPhr,
797 (trgCqi - crntCqi) * RG_SCH_UL_CQI_DB_STEP_2));
798 } /* rgSCHPwrGetDelta2FrmCqi */
800 /***********************************************************
802 * Func : rgSCHPwrGetPuschTpc
804 * Desc : Based on whether accumulation is enabled or
805 * not, this returns an applicable power delta
806 * to be applied based on the input delta.
814 **********************************************************/
816 PRIVATE Void rgSCHPwrGetPuschTpc
825 PRIVATE Void rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, tpc, tpcDelta)
833 TRC2(rgSCHPwrGetPuschTpc);
835 delta = RGSCH_MIN(delta, availPwr);
837 /* As of now, the functions below possibly cause delta
838 * to be breached by 1 only. So calling these as is. */
841 rgSCHPwrGetAcc2bitTpc(delta, tpc, tpcDelta);
845 rgSCHPwrGetAbsTpc(delta, tpc, tpcDelta);
848 } /* rgSCHPwrGetPuschTpc */
850 /***********************************************************
852 * Func : rgSCHPwrGetMaxRb
854 * Desc : Get the maximum number of RBs that can be
855 * expected to be supported by the passed
864 **********************************************************/
866 PRIVATE U8 rgSCHPwrGetMaxRb
872 PRIVATE U8 rgSCHPwrGetMaxRb(cell, pwr)
877 RgSchCmnUlCell *cellUl;
879 TRC2(rgSCHPwrGetMaxRb);
881 cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
884 /* Give 4 RBS so that UE can report changed power status*/
885 /* [ccpu00119916] Mod -return 0th index of rgSchPwrToRbTbl when pwr <=0
886 * Change the Macros from RGSCH_MAX_DL_BW to RGSCH_MAX_UL_BW*/
887 RETVALUE(rgSchPwrToRbTbl[0]);
889 if (pwr > rgSchPwrRbToPwrTbl[cellUl->maxUlBwPerUe])
891 RETVALUE(cellUl->maxUlBwPerUe);
893 RETVALUE(RGSCH_MIN(cellUl->maxUlBwPerUe,rgSchPwrToRbTbl[(U8)pwr]));
894 } /* rgSCHPwrGetMaxRb */
896 /***********************************************************
898 * Func : rgSCHPwrRbToPwr
900 * Desc : Get the power corresponding to number of RBs
908 **********************************************************/
910 PRIVATE U8 rgSCHPwrRbToPwr
916 PRIVATE U8 rgSCHPwrRbToPwr(cell,numRb)
922 RgSchCmnUlCell *cellUl;
924 TRC2(rgSCHPwrRbToPwr);
925 #if (ERRCLASS & ERRCLS_DEBUG)
926 cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
927 if (numRb > cellUl->maxUlBwPerUe)
929 numRb = cellUl->maxUlBwPerUe;
932 RETVALUE(rgSchPwrRbToPwrTbl[numRb]);
933 } /* rgSCHPwrRbToPwr */
937 * @brief Handles Pucch power control for DCI formats 1A/1B/1D/1/2A/2
941 * Function : rgSCHPwrPucchCntrl
944 * - Determine 2 bit TPC to be sent using remPucchPwr.
945 * - Update remPucchPwr appropriately
947 * @param[in] RgSchCellCb *cell
948 * @param[in] RgSchUeCb *ue
952 PRIVATE Void rgSCHPwrPucchCntrl
958 PRIVATE Void rgSCHPwrPucchCntrl(cell, ue)
964 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
965 TRC2(rgSCHPwrPucchCntrl);
967 rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, &uePwr->pucchTpc, &delta);
968 rgSCHPwrOnSchedPucchTpc(cell, ue, delta);
973 * @brief Handles group power control for DCI formats 3/3A for Pucch and Pusch
977 * Function : rgSCHPwrGrpCntrlPucch
979 * Invoking Module Processing:
980 * - This shall be invoked to do group power control for
981 * all TPC RNTIs for which it is deemed necessary to
982 * do the same (group power control).
983 * - This function should only be invoked after all UEs
984 * have been scheduled for uplink (re)transmissions
985 * requiring DL DCI format in the passed subframe.
988 * - For Pucch group power control
989 * - For each TPC-Pucch-RNTI in the pucchGrpPwr List and
990 * TPC-Pusch-RNTI in the puschGrpPwr List,
991 * - Request for PDCCH, skip if not available
992 * - Form DCI format 3/3A information depending
993 * on the format type of the TPC-RNTI and add it to the sub-frame.
994 * - For each Ue in ueLst of TPC RNTI Cb
995 * - if (fmtType == 3A)
996 * - if((Ue not scheduled DL dci formats)
997 * && (remPwr >= 2 || remPwr <= -2))
998 * - Determine TPC. Set puschTpc/pucchTpc.
1000 * - if (remPwr >= -1 && remPwr <= 1)
1001 * - If already added, remove from toBeSchdLst
1003 * - Toggle the remainig power value
1004 * - else if (fmtType == 3)
1005 * - if((Ue not scheduled DL dci formats)
1007 * - Determine TPC. Set puschTpc/pucchTpc.
1010 * - If already added, remove from toBeSchdLst
1011 * - if (!toBeSchdUeCnt)
1012 * - Remove the tpcRntiCb frm pucchGrpPwr/puschGrpPwr List
1013 * - else, Move the tpcRntiCb to end of the list (not doing
1016 * @param[in] RgSchCellCb *cell
1017 * @param[in] RgSchDlSf *dlSf
1021 PUBLIC Void rgSCHPwrGrpCntrlPucch
1027 PUBLIC Void rgSCHPwrGrpCntrlPucch(cell, dlSf)
1032 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
1036 TRC2(rgSCHPwrGrpCntrlPucch);
1038 lst = &cellPwr->pucchGrpPwr;
1040 while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1042 RgSchCmnTpcRntiCb *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1045 rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, &sched);
1048 rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1050 /* TPC RNTI would not have been removed if needs to
1051 * be scheduled again */
1058 * @brief Handles group power control for DCI formats 3/3A for Pusch and Pusch
1062 * Function : rgSCHPwrGrpCntrlPusch
1064 * Invoking Module Processing:
1065 * - This shall be invoked to do group power control for
1066 * all TPC RNTIs for which it is deemed necessary to
1067 * do the same (group power control).
1068 * - This function should only be invoked after all UEs
1069 * have been scheduled for uplink (re)transmissions
1070 * requiring DCI format 0 in the passed subframe.
1073 * - For Pusch group power control
1074 * - For each TPC-Pusch-RNTI in the puschGrpPwr List and
1075 * - Request for PDCCH, skip if not available
1076 * - Form DCI format 3/3A information depending
1077 * on the format type of the TPC-RNTI and add it to the sub-frame.
1078 * - For each Ue in ueLst of TPC RNTI Cb
1079 * - if (fmtType == 3A)
1080 * - if (Ue not scheduled for dci format 0) and
1081 * (remPwr >= 2 || remPwr <= -2))
1082 * - Determine TPC. Set puschTpc/puschTpc.
1084 * - if (remPwr >= -1 && remPwr <= 1)
1085 * - If already added, remove from toBeSchdLst
1087 * - Toggle the remainig power value
1088 * - else if (fmtType == 3)
1089 * - if((Ue not scheduled for dci format 0) && (remPwr))
1090 * - Determine TPC. Set puschTpc.
1093 * - If already added, remove from toBeSchdLst
1094 * - if (!toBeSchdUeCnt)
1095 * - Remove the tpcRntiCb frm puschGrpPwr/puschGrpPwr List
1096 * - else, Move the tpcRntiCb to end of the list (not doing
1099 * @param[in] RgSchCellCb *cell
1100 * @param[in] RgSchDlSf *sf
1104 PUBLIC Void rgSCHPwrGrpCntrlPusch
1111 PUBLIC Void rgSCHPwrGrpCntrlPusch(cell, dlSf, ulSf)
1117 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
1121 TRC2(rgSCHPwrGrpCntrlPusch);
1123 lst = &cellPwr->puschGrpPwr;
1125 while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1127 RgSchCmnTpcRntiCb *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1130 rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, &sched);
1133 rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1135 /* TPC RNTI would not have been removed if needs to
1136 * be scheduled again */
1142 /***********************************************************
1144 * Func : rgSCHPwrSchedPucchRnti
1146 * Desc : Schedule TPC RNTI to be sent out
1154 **********************************************************/
1156 PRIVATE Void rgSCHPwrSchedPucchRnti
1159 RgSchCmnTpcRntiCb *cb,
1165 PRIVATE Void rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, sched)
1167 RgSchCmnTpcRntiCb *cb;
1179 TRC2(rgSCHPwrSchedPucchRnti);
1181 pdcch->rnti = cb->tpcRnti;
1185 /* Go through all UEs for format 3A case */
1187 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1188 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1189 pdcch->dci.u.format3AInfo.isPucch = TRUE;
1191 tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1192 /* No need to memset zero initially as every TPC is going
1193 * to be filled up for every configured UE */
1194 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1196 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1197 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1199 if ( ue->isDrxEnabled == TRUE &&
1200 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1202 /* UE is in its DRX time. So we cannot give command
1208 if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1210 /* UE already scheduled in downlink with PDCCH
1211 * carrying PUCCH pwr cmd. So don't care about
1212 * giving command to this UE. */
1215 rgSCHPwrGetPucchFmt3aTpcForUe(ue, &tpc, &delta);
1216 tpcCmds[uePwr->pucchIdx] = tpc;
1218 rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1223 /* Go through to-be-scheduled UEs for format 3 case */
1224 lst = &cb->toBeSchdUes;
1225 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1226 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1227 tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1228 pdcch->dci.u.format3Info.isPucch = TRUE;
1230 /* Fill TPC 1 (corresponding to no power change) initially */
1231 cmMemset((U8 *)tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1233 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1235 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1236 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1238 if ( ue->isDrxEnabled == TRUE &&
1239 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1241 /* UE is in its DRX time. So we cannot give command
1247 if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1249 /* UE already scheduled in downlink with PDCCH
1250 * carrying PUCCH pwr cmd. So don't care about
1251 * giving command to this UE. */
1254 rgSCHPwrGetPucchFmt3TpcForUe(ue, &tpc, &delta);
1255 tpcCmds[uePwr->pucchIdx] = tpc;
1257 rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1261 *sched = atleastOne;
1263 /* Check if no more UEs in TPC RNTI, and then remove
1264 * this TPC RNTI from scheduled list */
1265 if (cb->toBeSchdUes.count == 0)
1267 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
1271 } /* rgSCHPwrSchedPucchRnti */
1273 /***********************************************************
1275 * Func : rgSCHPwrSchedPuschRnti
1277 * Desc : Schedule TPC RNTI to be sent out
1285 **********************************************************/
1287 PRIVATE Void rgSCHPwrSchedPuschRnti
1290 RgSchCmnTpcRntiCb *cb,
1296 PRIVATE Void rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, sched)
1298 RgSchCmnTpcRntiCb *cb;
1310 TRC2(rgSCHPwrSchedPuschRnti);
1312 pdcch->rnti = cb->tpcRnti;
1316 /* Go through all UEs for format 3A case */
1318 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1319 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1320 pdcch->dci.u.format3AInfo.isPucch = FALSE;
1321 tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1322 /* No need to memset zero initially as every TPC is going
1323 * to be filled up for every configured UE */
1324 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1326 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1327 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1328 if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1330 /* UE already scheduled in uplink with DCI
1331 * format 0. So don't care about giving
1332 * command to this UE. */
1336 if ( ue->isDrxEnabled == TRUE &&
1337 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1339 /* UE is in its DRX time. So we cannot give command
1345 rgSCHPwrGetPuschFmt3aTpcForUe(ue, &tpc, &delta);
1346 tpcCmds[uePwr->puschIdx] = tpc;
1348 rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1353 /* Go through to-be-scheduled UEs for format 3 case */
1354 lst = &cb->toBeSchdUes;
1355 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1356 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1357 pdcch->dci.u.format3Info.isPucch = FALSE;
1358 tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1360 /* Fill TPC 1 (corresponding to no power change) initially */
1361 cmMemset((U8 *)tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1363 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1365 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1366 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1367 if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1369 /* UE already scheduled in uplink with DCI
1370 * format 0. So don't care about giving
1371 * command to this UE. */
1375 if ( ue->isDrxEnabled == TRUE &&
1376 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1378 /* UE is in its DRX time. So we cannot give command
1384 rgSCHPwrGetPuschFmt3TpcForUe(ue, &tpc, &delta);
1385 tpcCmds[uePwr->puschIdx] = tpc;
1387 rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1391 *sched = atleastOne;
1393 /* Check if no more UEs in TPC RNTI, and then remove
1394 * this TPC RNTI from scheduled list */
1395 if (cb->toBeSchdUes.count == 0)
1397 rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
1401 } /* rgSCHPwrSchedPuschRnti */
1403 /***********************************************************
1405 * Func : rgSCHPwrGetPucchFmt3TpcForUe
1407 * Desc : Gets 2 bit TPC cmd for PUCCH
1415 **********************************************************/
1417 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe
1424 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe(ue, tpc, delta)
1430 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1431 TRC2(rgSCHPwrGetPucchFmt3TpcForUe);
1433 rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, tpc, delta);
1435 } /* rgSCHPwrGetPucchFmt3TpcForUe */
1437 /***********************************************************
1439 * Func : rgSCHPwrGetPucchFmt3aTpcForUe
1441 * Desc : Gets 1 bit TPC cmd for PUCCH
1449 **********************************************************/
1451 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe
1458 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe(ue, tpc, delta)
1464 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1465 TRC2(rgSCHPwrGetPucchFmt3aTpcForUe);
1467 rgSCHPwrGetAcc1bitTpc(uePwr->remPucchPwr, tpc, delta);
1469 } /* rgSCHPwrGetPucchFmt3aTpcForUe */
1471 /***********************************************************
1473 * Func : rgSCHPwrGetPuschFmt3TpcForUe
1475 * Desc : Gets 2 bit TPC cmd for PUCCH
1483 **********************************************************/
1485 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe
1492 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe(ue, tpc, delta)
1498 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1499 S8 adj = RGSCH_MIN(uePwr->remPuschPwr, uePwr->phVal);
1500 TRC2(rgSCHPwrGetPuschFmt3TpcForUe);
1502 rgSCHPwrGetAcc2bitTpc(adj, tpc, delta);
1504 } /* rgSCHPwrGetPuschFmt3TpcForUe */
1506 /***********************************************************
1508 * Func : rgSCHPwrGetPuschFmt3aTpcForUe
1510 * Desc : Gets 1 bit TPC cmd for PUCCH
1518 **********************************************************/
1520 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe
1527 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe(ue, tpc, delta)
1533 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1534 TRC2(rgSCHPwrGetPuschFmt3aTpcForUe);
1536 /* Don't attempt to look at headroom now, power
1537 * adjustment is small anyway */
1538 rgSCHPwrGetAcc1bitTpc(uePwr->remPuschPwr, tpc, delta);
1540 } /* rgSCHPwrGetPuschFmt3aTpcForUe */
1542 /***********************************************************
1544 * Func : rgSCHPwrGetAcc1bitTpc
1546 * Desc : Gets 1 bit TPC cmd
1554 **********************************************************/
1556 PRIVATE Void rgSCHPwrGetAcc1bitTpc
1563 PRIVATE Void rgSCHPwrGetAcc1bitTpc(remPwr, tpc, delta)
1569 TRC2(rgSCHPwrGetAcc1bitTpc);
1586 } /* rgSCHPwrGetAcc1bitTpc */
1588 /***********************************************************
1590 * Func : rgSCHPwrGetAcc2bitTpc
1592 * Desc : Allocate PDCCH for group power control
1600 **********************************************************/
1602 PRIVATE Void rgSCHPwrGetAcc2bitTpc
1609 PRIVATE Void rgSCHPwrGetAcc2bitTpc(remPwr, tpc, delta)
1622 U8 tpcs[3] = {1, 2, 2};
1623 U8 deltas[3] = {0, 1, 1};
1624 TRC2(rgSCHPwrGetAcc2bitTpc);
1630 else if (remPwr >= 3)
1637 *tpc = tpcs[(U8)remPwr];
1638 *delta = deltas[(U8)remPwr];
1641 } /* rgSCHPwrGetAcc2bitTpc */
1643 /***********************************************************
1645 * Func : rgSCHPwrGetAbsTpc
1647 * Desc : Allocate PDCCH for group power control
1655 **********************************************************/
1657 PRIVATE Void rgSCHPwrGetAbsTpc
1664 PRIVATE Void rgSCHPwrGetAbsTpc(remPwr, tpc, delta)
1670 TRC2(rgSCHPwrGetAbsTpc);
1683 else if (remPwr < 1)
1688 else if (remPwr < 4)
1699 } /* rgSCHPwrGetAbsTpc */
1701 /***********************************************************
1703 * Func : rgSCHPwrOnPucchGrpPwrForUe
1705 * Desc : Processing on sending TPC for UE through group power
1706 * control. Apart from updating remPwr, this only takes
1707 * care of possibly removing UE from scheduled
1709 * It does not take care of possibly removing TPC RNTI
1710 * from scheduled list in cell. This is done
1711 * in the caller after TPC for all UEs has been
1712 * determined. (This is where it differs
1713 * from the usual OnSendingPu[cs]ch TPC]
1721 **********************************************************/
1723 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe
1730 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta)
1736 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1741 TRC2(rgSCHPwrOnPucchGrpPwrForUe);
1743 uePwr->remPucchPwr -= delta;
1745 /* UE was already scheduled for PUCCH group power
1746 * control which is why we came here. Don't
1747 * again check for this. */
1749 /* UE was scheduled for pucch grp pwr, sent TPC may
1750 * possibly cause it to be removed. */
1751 if (!uePwr->remPucchPwr)
1757 rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
1758 /* Not removing TPC RNTI from scheduled list,
1759 * this will happen in the caller once this
1760 * function is called for every UE scheduled. */
1765 /***********************************************************
1767 * Func : rgSCHPwrOnPuschGrpPwrForUe
1769 * Desc : Processing on sending TPC for UE through group power
1770 * control. Apart from updating remPwr, this only takes
1771 * care of possibly removing UE from scheduled
1773 * It does not take care of possibly removing TPC RNTI
1774 * from scheduled list in cell. This is done
1775 * in the caller after TPC for all UEs has been
1776 * determined. (This is where it differs
1777 * from the usual OnSendingPu[cs]ch TPC]
1785 **********************************************************/
1787 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe
1794 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta)
1800 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1804 TRC2(rgSCHPwrOnPuschGrpPwrForUe);
1806 uePwr->delta = delta;
1807 uePwr->remPuschPwr -= delta;
1808 if (uePwr->isPhrAvail)
1810 uePwr->phVal -= uePwr->delta;
1811 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1814 /* UE was already scheduled for PUSCH group power
1815 * control which is why we came here. Don't
1816 * again check for this. */
1818 /* UE was scheduled for pusch grp pwr, sent TPC may
1819 * possibly cause it to be removed. */
1821 if (!uePwr->remPuschPwr)
1828 rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
1829 /* Not removing TPC RNTI from scheduled list,
1830 * this will happen in the caller once this
1831 * function is called for every UE scheduled. */
1836 /***********************************************************
1838 * Func : rgSCHPwrIsDlUeSched
1840 * Desc : Check if UE is scheduled in the passed DL SF
1848 **********************************************************/
1850 PRIVATE Bool rgSCHPwrIsDlUeSched
1857 PRIVATE Bool rgSCHPwrIsDlUeSched(cell, ue, sf)
1863 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1864 RgSchDlHqProcCb *proc = rgSCHDhmLastSchedHqProc(hqEnt);
1866 TRC2(rgSCHPwrIsDlUeSched);
1874 * The following subframe check is assumed enough, since
1875 * scheduled procs stay for a short time (until feedback
1876 * arrives), which typically is expected to have a
1877 * turnaround time of less than 8 subframes. So
1878 * we are probably never going to come across cases
1879 * where a process stays in the list for more than
1880 * 10 subframes, which would have otherwise caused
1881 * the check to succeed for a possibly older process.
1883 if ((proc->tbInfo[0].timingInfo.subframe == sf->sfNum) ||
1884 (proc->tbInfo[1].timingInfo.subframe == sf->sfNum))
1887 * Later, if a proc can be scheduled without having an
1888 * associated PDCCH, need to also check if PDCCH exists.
1889 * This is because for power, what matters is whether
1890 * TPC is going out for UE at this time or not, at least
1891 * that is what this function was introduced for.
1892 * Checking for PDCCH would have to be in common proc
1893 * the way things are now.
1901 } /* rgSCHPwrIsDlUeSched */
1903 /***********************************************************
1905 * Func : rgSCHPwrIsUlUeSched
1907 * Desc : Check if UE is scheduled in the passed UL SF
1915 **********************************************************/
1917 PRIVATE Bool rgSCHPwrIsUlUeSched
1924 PRIVATE Bool rgSCHPwrIsUlUeSched(cell, ue, sf)
1930 RgSchCmnUlCell *cmnCell = RG_SCH_CMN_GET_UL_CELL(cell);
1931 RgSchUlHqProcCb *proc = rgSCHUhmGetUlHqProc(cell, ue, cmnCell->schdHqProcIdx);
1933 TRC2(rgSCHPwrIsUlUeSched);
1937 #if (ERRCLASS & ERRCLS_DEBUG)
1952 } /* rgSCHPwrIsUlUeSched */
1955 * @brief Handles Pucch power delta indication recieved from PHY
1959 * Function : rgSCHPwrPucchDeltaInd
1961 * Invoking Module Processing:
1962 * - This shall be invoked on reception of Pucch power
1963 * delta indication from PHY.
1966 * - Update the remPucchPwr
1967 * ue->remPucchPwr = pwrDelta
1968 * - If (ue->tpcPucchRntiCb)
1969 * - If (fmtType = 3A)
1970 * - if (remPucchPwr >= 2 || remPucchPwr <= -2 )
1971 * - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1972 * - Add tpcPucchRntiCb to the pucchGrpPwr list.
1973 * - If not added, add to toBeSchdLst
1975 * - If already added, remove from toBeSchdLst
1976 * - else If (fmtType == 3)
1977 * - if (remPucchPwr)
1978 * - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1979 * - Add tpcPucchRntiCb to the pucchGrpPwr list.
1980 * - If not added, add to toBeSchdLst
1982 * - If already added, remove from toBeSchdLst
1984 * @param[in] RgSchCellCb *cell
1985 * @param[in] RgSchUeCb *ue
1986 * @param[in] U8 pwrDelta
1990 PUBLIC Void rgSCHPwrPucchDeltaInd
1997 PUBLIC Void rgSCHPwrPucchDeltaInd(cell, ue, pwrDelta)
2003 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2004 RgSchCmnTpcRntiCb *cb;
2006 TRC2(rgSCHPwrPucchDeltaInd);
2008 uePwr->remPucchPwr = pwrDelta;
2010 if ((cb = uePwr->tpcPucchRntiCb) == NULLP)
2017 if (0 != uePwr->remPucchPwr)
2025 rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue);
2029 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
2036 * @brief Does processing after TPC for Pucch has been sent
2040 * Function : rgSCHPwrOnSchedPucchTpc
2042 * Invoking Module Processing:
2043 * - It shall be invoked after it is determined that PDCCH for UE
2044 * is finalised to go out, and thus TPC for PUCCH is being
2048 * - Update remPucchPwr with the delta
2049 * - Do group power control related processing
2051 * @param[in] RgSchCellCb *cell
2052 * @param[in] RgSchUeCb *ue
2053 * @param[in] S8 delta
2057 PRIVATE Void rgSCHPwrOnSchedPucchTpc
2064 PRIVATE Void rgSCHPwrOnSchedPucchTpc(cell, ue, delta)
2070 /* Similar to rgSCHPwrPucchDeltaInd.. not reusing
2071 * that since we use the fact that UE could only have
2072 * improved its remPwr as part of power control. */
2073 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2075 TRC2(rgSCHPwrOnSchedPucchTpc);
2077 uePwr->remPucchPwr -= delta;
2079 if (uePwr->schdPucchGrpLnk.node == NULLP)
2084 /* UE was scheduled for TPC, sent TPC may
2085 * possibly cause it to be removed. */
2087 if (!uePwr->remPucchPwr)
2094 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2095 if (uePwr->tpcPucchRntiCb->toBeSchdUes.count == 0)
2097 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb);
2105 * @brief Does processing after TPC for Pusch has been sent
2109 * Function : rgSCHPwrOnSchedPuschTpc
2113 * - Update remPuschPwr with the delta
2114 * - Do group power related processing if applicable
2116 * @param[in] RgSchCellCb *cell
2117 * @param[in] RgSchUeCb *ue
2121 PRIVATE Void rgSCHPwrOnSchedPuschTpc
2127 PRIVATE Void rgSCHPwrOnSchedPuschTpc(cell, ue)
2132 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2134 TRC2(rgSCHPwrOnSchedPuschTpc);
2136 /* Don't do anything for the case of absolute TPC commands */
2137 if (!uePwr->isAccumulated)
2142 uePwr->remPuschPwr -= uePwr->delta;
2143 if (uePwr->isPhrAvail)
2145 uePwr->phVal -= uePwr->delta;
2146 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2149 if (uePwr->schdPuschGrpLnk.node == NULLP)
2154 /* UE was scheduled for pusch TPC, sent TPC may
2155 * possibly cause it to be removed. */
2157 if (!uePwr->remPuschPwr)
2164 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2171 * @brief Handles PHR updation for the UE
2175 * Function : rgSCHPwrUpdExtPhr
2176 * @param[in] RgSchCellCb *cell
2177 * @param[in] RgSchUeCb *ue
2178 * @param[in] RgInfExtPhrCEInfo *extPhr
2179 * @param[in] RgSchCmnAllocRecord allocInfo
2183 PUBLIC Void rgSCHPwrUpdExtPhr
2187 RgInfExtPhrCEInfo *extPhr,
2188 RgSchCmnAllocRecord *allocInfo
2191 PUBLIC Void rgSCHPwrUpdExtPhr(cell, ue, extPhr, allocInfo)
2194 RgInfExtPhrCEInfo *extPhr;
2195 RgSchCmnAllocRecord *allocInfo;
2199 RgInfExtPhrSCellInfo *servCellPhr;
2202 TRC2(rgSCHPwrUpdExtPhr);
2204 for (idx = 0; idx < extPhr->numServCells; idx++)
2206 servCellPhr = &extPhr->servCellPhr[idx];
2208 if (RG_SCH_REF_PCMAX == servCellPhr->pCmax)
2210 pCMax = RG_SCH_CMN_PWR_USE_CFG_MAX_PWR;
2214 pCMax = rgSCHPwrGetPCMaxValFromPCMax(servCellPhr->pCmax);
2216 rgSCHPwrUpdPhr(ue->cellInfo[servCellPhr->sCellIdx]->cell,
2217 ue, servCellPhr->phr, allocInfo, pCMax);
2223 * @brief Handles PHR updation for the UE
2227 * Function : rgSCHPwrUpdPhr
2229 * Invoking Module Processing:
2230 * - This shall be invoked on reception of PHR from MAC to SCH. It shall
2231 * pass the information of number of RBs, coding efficiency and TPC for
2232 * the Pusch transmission for which PHR has been reported.
2235 * - Compute power per RB using the PHR report
2236 * - ue_transmit_pwr = ue_max_pwr - PHR
2237 * - if isDeltaMcs = TRUE
2238 * - ue_transmit_pwr -
2239 * [10log(phr_num_rb) + 10log(2^ (1.25 * phr_coding_effeciency) -1)
2240 * + phr_tpc(if absolute TPC)] = pwrPerRB
2242 * - ue_transmit_pwr - [10log(phr_num_rb) + phr_tpc(if absolute TPC)]
2244 * (Use the number of RBs and efficiency used by UE which caused the PHR
2246 * - Adjust PHR according to last allocation (take into account
2247 * number of RBs granted in the last allocation)
2248 * - Update the PHR report in the control block
2249 * - Set isPhrAvail = TRUE
2250 * - Do group power control related processing if applicable
2252 * @param[in] RgSchCellCb *cell
2253 * @param[in] RgSchUeCb *ue
2255 * @param[in] RgSchCmnAllocRecord allocInfo
2256 * @param[in] U8 maxUePwr
2260 PUBLIC Void rgSCHPwrUpdPhr
2265 RgSchCmnAllocRecord *allocInfo,
2269 PUBLIC Void rgSCHPwrUpdPhr(cell, ue, phr, allocInfo, maxUePwr)
2273 RgSchCmnAllocRecord *allocInfo;
2277 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2280 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2282 TRC2(rgSCHPwrUpdPhr);
2284 uePwr->phVal = rgSCHPwrGetPhValFromPhr(phr);
2286 if (maxUePwr == RG_SCH_CMN_PWR_USE_CFG_MAX_PWR)
2288 maxUePwr = uePwr->maxUePwr;
2290 rbPwr = rgSCHPwrRbToPwr(cell,allocInfo->numRb);
2291 effPwr = rgSCHPwrGetCqiPwrForUe(cell, ue, allocInfo->cqi);
2292 uePwr->pwrPerRb = maxUePwr - uePwr->phVal - rbPwr - effPwr;
2293 /*if (!uePwr->isAccumulated)
2295 uePwr->pwrPerRb -= rgSCHPwrGetDeltaFrmAbsTpc(allocInfo->tpc);
2298 /* Let headroom reflect remaining power according to last
2299 * allocated number of RBs. Intermediate TPCs not yet
2300 * taken care of (for accumulated case, it is anyway
2301 * not applicable for absolute commands). */
2302 uePwr->phVal -= (rgSCHPwrRbToPwr(cell, cellUl->sbSize)) - rbPwr;
2303 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2304 uePwr->isPhrAvail = TRUE;
2306 rgSCHPwrOnPuschPwrUpd(cell, ue);
2308 RLOG_ARG4(L_DEBUG,DBG_UEID,ue->ueId,
2309 "Output: Reported PHR[%d] cqi[%u] allocRb[%u] uePwr->pwrPerRb[%d]",
2318 * @brief Handles UL CQI indication
2322 * Function : rgSCHPwrUlCqiInd
2324 * Invoking Module Processing:
2325 * - This shall be invoked when uplink CQI indication
2326 * is receiving from PHY for a UE.
2329 * - Update remPuschPwr.
2330 * - Possibly schedule for group power control.
2332 * @param[in] RgSchCellCb *cell
2333 * @param[in] RgSchUeCb *ue
2334 * @param[in] U8 numRb
2338 PUBLIC Void rgSCHPwrUlCqiInd
2344 PUBLIC Void rgSCHPwrUlCqiInd(cell, ue)
2349 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2350 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2354 TRC2(rgSCHPwrUlCqiInd);
2357 * For absolute power cmd case, we could look at the time
2358 * at which CQI was received, determine if there was a
2359 * PUSCH TPC cmd for that time (this could come from
2360 * group power control too), and (if this
2361 * CQI report is indeed based on the the PUSCH tx)
2362 * then factor in that cmd here. Not doing
2366 /* See how much power needs to be adjusted based on cqi
2368 uePwr->remPuschPwr =
2370 rgSCHPwrGetDelta2FrmCqi(ueUl->validUlCqi, uePwr->trgCqi, ue, cell);
2372 rgSCHPwrGetDelta2FrmCqi(ueUl->crntUlCqi[0], uePwr->trgCqi, ue, cell);
2375 rgSCHPwrOnPuschPwrUpd(cell, ue);
2377 if(uePwr->maxPwrDeltaByPhr < 0)
2379 tmp = ueUl->validUlCqi;
2380 tmp = tmp + uePwr->maxPwrDeltaByPhr;
2383 ueUl->validUlCqi = 1;
2387 ueUl->validUlCqi = tmp;
2396 * @brief Updates the stored last number of RBs allocated
2400 * Function : rgSCHPwrRecordRbAlloc
2402 * Invoking Module Processing:
2403 * - This shall be invoked when uplink allocation is made for
2405 * - Note: If outstanding TPCs are considered at the time
2406 * of PHR report, the last numRb would also be known
2407 * and then this API would not be needed.
2410 * - Adjust PHR according to now allocated number of RBs
2411 * - Store the number of RBs
2413 * @param[in] RgSchCellCb *cell
2414 * @param[in] RgSchUeCb *ue
2415 * @param[in] U8 numRb
2419 PUBLIC Void rgSCHPwrRecordRbAlloc
2426 PUBLIC Void rgSCHPwrRecordRbAlloc(cell, ue, numRb)
2432 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2434 TRC2(rgSCHPwrRecordRbAlloc);
2437 if (uePwr->isPhrAvail)
2439 uePwr->phVal += rgSCHPwrRbToPwr(cell,numRb) - rgSCHPwrRbToPwr(cell,uePwr->numRb);
2440 uePwr->phVal = RGSCH_MIN(40, uePwr->phVal);
2442 uePwr->numRb = numRb;
2447 * @brief Handles power related configuration for a cell
2451 * Function : rgSCHPwrCellCfg
2453 * Invoking Module Processing:
2454 * - This shall be invoked during cell config
2459 * - Update TPC-RNTI information for the cell for Pucch and Pusch.
2460 * - For each TPC-Pucch-RNTI,
2461 * - Call rgSCHAddRntiToPucchRntiLst()
2462 * - For each TPC-Pusch-RNTI,
2463 * - Call rgSCHAddRntiToPuschRntiLst()
2466 * @param[in] RgSchCellCb *cell
2467 * @param[in] RgrCellCfg *cfg
2473 PUBLIC S16 rgSCHPwrCellCfg
2479 PUBLIC S16 rgSCHPwrCellCfg(cell, cfg)
2484 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2486 CmLteRnti startRnti;
2489 TRC2(rgSCHPwrCellCfg);
2491 /* Right now, all UEs have fixed maximum power capability. So
2492 * we store cell wide pMax as minimum of configured pMax and
2494 cellPwr->pMax = RGSCH_MIN(cfg->pMax, RG_SCH_PWR_UE_MAX_PWR);
2496 /* trgUlCqi already validated by common */
2497 cellPwr->trgUlCqi = cfg->trgUlCqi.trgCqi;
2499 /* Validate number of TPC RNTIs */
2500 if ((cfg->pwrCfg.pucchPwrFmt3.size + cfg->pwrCfg.pucchPwrFmt3a.size
2501 > RG_SCH_CMN_MAX_NUM_TPC_PUCCH_RNTI)
2502 || (cfg->pwrCfg.puschPwrFmt3.size + cfg->pwrCfg.puschPwrFmt3a.size
2503 > RG_SCH_CMN_MAX_NUM_TPC_PUSCH_RNTI))
2508 /* Now initialise TPC RNTIs */
2510 /* Format 3 Pucch TPC RNTIs */
2512 startRnti = cfg->pwrCfg.pucchPwrFmt3.startTpcRnti;
2513 size = cfg->pwrCfg.pucchPwrFmt3.size;
2514 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2516 rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2519 /* Format 3A Pucch TPC RNTIs */
2521 startRnti = cfg->pwrCfg.pucchPwrFmt3a.startTpcRnti;
2522 size = cfg->pwrCfg.pucchPwrFmt3a.size;
2523 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2525 rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2528 /* Format 3 Pusch TPC RNTIs */
2530 startRnti = cfg->pwrCfg.puschPwrFmt3.startTpcRnti;
2531 size = cfg->pwrCfg.puschPwrFmt3.size;
2532 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2534 rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2537 /* Format 3A Pusch TPC RNTIs */
2539 startRnti = cfg->pwrCfg.puschPwrFmt3a.startTpcRnti;
2540 size = cfg->pwrCfg.puschPwrFmt3a.size;
2541 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2543 rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2550 * @brief Handles power related re-configuration for a cell
2554 * Function : rgSCHPwrCellRecfg
2559 * @param[in] RgSchCellCb *cell
2560 * @param[in] RgrCellRecfg *recfg
2565 PUBLIC S16 rgSCHPwrCellRecfg
2571 PUBLIC S16 rgSCHPwrCellRecfg(cell, recfg)
2573 RgrCellRecfg *recfg;
2578 TRC2(rgSCHPwrCellRecfg);
2580 /* Not doing anything for power reconfig, so such structure
2586 * @brief Frees power related data structures in cell
2590 * Function : rgSCHPwrCellDel
2595 * @param[in] RgSchCellCb *cell
2599 PUBLIC Void rgSCHPwrCellDel
2604 PUBLIC Void rgSCHPwrCellDel(cell)
2609 TRC2(rgSCHPwrCellDel);
2611 /* There is no allocated memory, so do nothing */
2618 * @brief Configures ULPC CB for a SCELL being added
2622 * Function : rgSCHPwrUeSCellCfg
2624 * @param[in] RgSchCellCb *cell
2625 * @param[in] RgSchUeCb *ue
2626 * @param[in] RgrUeCfg *cfg
2632 PUBLIC S16 rgSCHPwrUeSCellCfg
2636 RgrUeSecCellCfg *sCellInfoCfg
2639 PUBLIC S16 rgSCHPwrUeSCellCfg(cell, ue, sCellInfoCfg)
2642 RgrUeSecCellCfg *sCellInfoCfg;
2645 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2646 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2647 RgSchCmnUeUlPwrCb *uePwrPCell = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2648 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2650 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2652 TRC2(rgSCHPwrUeSCellCfg);
2654 uePwr->maxUePwr = cellPwr->pMax;
2655 uePwr->trgCqi = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2658 uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2660 uePwr->isPhrAvail = FALSE;
2662 uePwr->maxUlRbs = RGSCH_MAX_DL_BW;
2664 uePwr->puschTpc = 1;
2665 uePwr->remPuschPwr = 0;
2667 /* Rest of the vars update and group power control related
2668 * config happens in the function below */
2669 uePwr->isAccumulated = sCellInfoCfg->ueSCellUlDedPwrCfg.isAccumulated;
2670 uePwr->deltaMcsEnbld = sCellInfoCfg->ueSCellUlDedPwrCfg.isDeltaMCSEnabled;
2672 uePwr->trgCqi = uePwrPCell->trgCqi;
2674 if (ueUl->maxUlCqi < uePwr->trgCqi)
2676 uePwr->trgCqi = ueUl->maxUlCqi;
2678 uePwr->p0UePusch = sCellInfoCfg->ueSCellUlDedPwrCfg.p0UePusch;
2685 * @brief Handles power related configuration for a UE
2689 * Function : rgSCHPwrUeCfg
2692 * - If Pusch group power configuration exists && accumulation enabled,
2693 * - Fetch the TPC-Pusch-RNTI control block for the configured
2694 * TPC-Pusch-RNTI. Call rgSCHGetRntiFrmPuschRntiLst(). If it does not
2695 * exist, return RFAILED.
2696 * - Add Ue to the ueLst of TPC-Pusch-RNTI control block.
2697 * - Update tpcPuschRntiCb pointer in UE.
2698 * - Update the puschIdx value.
2699 * - If Pucch group power configuration exists && accumulation enabled,
2700 * - Fetch the TPC-Pucch-RNTI control block for the configured
2701 * TPC-Pucch-RNTI. Call rgSCHGetRntiFrmPucchRntiLst(). If it does not
2702 * exist, return RFAILED.
2703 * - Add Ue to the ueLst of TPC-Pucch-RNTI control block.
2704 * - Update tpcPucchRntiCb pointer in UE.
2705 * - Update the pucchIdx value.
2706 * - Update isAccumulated and isDeltaMcs variables.
2707 * - maxUlRbs = configured maximum UL bandwidth value per UE.
2708 * - trgUlCqi = configured value, if any, else cell-wide default trg CQI value.
2709 * - If format type is format 3A, update remaining power to +1
2710 * - Update TPC-RNTI information for the cell for Pucch and Pusch.
2713 * @param[in] RgSchCellCb *cell
2714 * @param[in] RgSchUeCb *ue
2715 * @param[in] RgrUeCfg *cfg
2721 PUBLIC S16 rgSCHPwrUeCfg
2728 PUBLIC S16 rgSCHPwrUeCfg(cell, ue, cfg)
2735 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2736 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2738 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2740 TRC2(rgSCHPwrUeCfg);
2742 uePwr->maxUePwr = cellPwr->pMax;
2743 uePwr->trgCqi = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2746 uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2748 rgSCHPwrUeResetPucch(cell, ue);
2749 rgSCHPwrUeResetPusch(cell, ue);
2751 /* Rest of the vars update and group power control related
2752 * config happens in the function below */
2753 ret = rgSCHPwrApplyUePwrCfg(cell, ue, &cfg->ueUlPwrCfg);
2759 * @brief Handles power related re-configuration for a UE
2763 * Function : rgSCHPwrUeRecfg
2765 * Invoking Module Processing:
2766 * - This shall be invoked by SCH_GOM at UE re-configuration.
2769 * - If change in TPC-RNTI, update the pointer and the TPC RNTI Cb appropriately.
2770 * - If accumulation disabled, remove the UE from TPC-RNTI lists of UE, if
2772 * - If group power configuration disabled, remove the UE from TPC-RNTI lists of UE, if
2775 * @param[in] RgSchCellCb *cell
2776 * @param[in] RgSchUeCb *ue
2777 * @param[in] RgrUeRecfg *recfg
2784 PUBLIC S16 rgSCHPwrUeRecfg
2791 PUBLIC S16 rgSCHPwrUeRecfg(cell, ue, recfg)
2798 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2799 RgrUeUlPwrCfg *pwrCfg = &recfg->ueUlPwrRecfg;
2800 TRC2(rgSCHPwrUeRecfg);
2802 if (pwrCfg->p0UePucch != uePwr->p0UePucch)
2804 rgSCHPwrUeResetPucch(cell, ue);
2806 if ((pwrCfg->isAccumulated != uePwr->isAccumulated)
2807 || (pwrCfg->p0UePusch != uePwr->p0UePusch))
2809 rgSCHPwrUeResetPusch(cell, ue);
2811 ret = rgSCHPwrApplyUePwrCfg(cell, ue, &recfg->ueUlPwrRecfg);
2816 /***********************************************************
2818 * Func : rgSCHPwrApplyUePwrCfg
2820 * Desc : Applies power config for UE. Meants to be
2821 * used during both power config and reconfig.
2829 **********************************************************/
2831 PRIVATE S16 rgSCHPwrApplyUePwrCfg
2835 RgrUeUlPwrCfg *pwrCfg
2838 PRIVATE S16 rgSCHPwrApplyUePwrCfg(cell, ue, pwrCfg)
2841 RgrUeUlPwrCfg *pwrCfg;
2845 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2846 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2847 RgSchCmnTpcRntiCb *pucchRntiCb = NULLP;
2848 RgSchCmnTpcRntiCb *puschRntiCb = NULLP;
2851 TRC2(rgSCHPwrApplyUePwrCfg);
2853 /* Validate Pucch group power control config */
2854 if (pwrCfg->uePucchPwr.pres)
2857 rgSCHPwrGetPucchRntiCb(cell, pwrCfg->uePucchPwr.tpcRnti);
2858 if (pucchRntiCb == NULLP)
2862 pucchIdx = pwrCfg->uePucchPwr.idx;
2863 ret = rgSCHPwrChkPucchTpcRntiIdx(pucchRntiCb, pucchIdx);
2870 /* Validate Pusch group power control config */
2871 if (pwrCfg->uePuschPwr.pres)
2874 rgSCHPwrGetPuschRntiCb(cell, pwrCfg->uePuschPwr.tpcRnti);
2875 if (puschRntiCb == NULLP)
2879 puschIdx = pwrCfg->uePuschPwr.idx;
2880 ret = rgSCHPwrChkPuschTpcRntiIdx(puschRntiCb, puschIdx);
2887 /* Apply Pucch group power control config */
2890 if (uePwr->tpcPucchRntiCb != pucchRntiCb) /* This part for recfg */
2892 if (uePwr->tpcPucchRntiCb)
2894 rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2896 uePwr->tpcPucchRntiCb = pucchRntiCb;
2897 rgSCHPwrAddUeToPucchTpcRntiCb(cell, pucchRntiCb, ue);
2899 uePwr->pucchIdx = pucchIdx;
2901 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2902 "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2903 pucchRntiCb->cfgdUes.count,((U32)pucchRntiCb->cfgdUes.first),
2904 ((U32)pucchRntiCb->cfgdUes.last),ue->ueId);
2905 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2906 "UEID:%d isFmt3a(%u) ueNode(%ld)",
2907 ue->ueId,pucchRntiCb->isFmt3a,
2908 pucchRntiCb->schdLnk.node);
2909 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2910 "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)",
2911 pucchRntiCb->toBeSchdUes.count,
2912 ((U32)pucchRntiCb->toBeSchdUes.first),
2913 ((U32)pucchRntiCb->toBeSchdUes.last),
2914 pucchRntiCb->tpcRnti);
2916 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2917 "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2918 pucchRntiCb->cfgdUes.count,((U64)pucchRntiCb->cfgdUes.first),
2919 ((U64)pucchRntiCb->cfgdUes.last),ue->ueId);
2920 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2921 "UEID:%d isFmt3a(%u) ueNode(%ld)",
2922 ue->ueId,pucchRntiCb->isFmt3a,
2923 pucchRntiCb->schdLnk.node);
2924 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2925 "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)",
2926 pucchRntiCb->toBeSchdUes.count,
2927 ((U64)pucchRntiCb->toBeSchdUes.first),
2928 ((U64)pucchRntiCb->toBeSchdUes.last),
2929 pucchRntiCb->tpcRnti);
2934 /* Apply Pusch group power control config */
2937 if (uePwr->tpcPuschRntiCb != puschRntiCb) /* This part for recfg */
2939 if (uePwr->tpcPuschRntiCb)
2941 rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2943 uePwr->tpcPuschRntiCb = puschRntiCb;
2944 rgSCHPwrAddUeToPuschTpcRntiCb(puschRntiCb, ue);
2946 uePwr->puschIdx = puschIdx;
2950 uePwr->isAccumulated = pwrCfg->isAccumulated;
2951 uePwr->deltaMcsEnbld = pwrCfg->isDeltaMCSEnabled;
2954 uePwr->trgCqi = pwrCfg->trgCqi;
2956 if (ueUl->maxUlCqi < uePwr->trgCqi)
2958 uePwr->trgCqi = ueUl->maxUlCqi;
2960 uePwr->p0UePusch = pwrCfg->p0UePusch;
2961 uePwr->p0UePucch = pwrCfg->p0UePucch;
2968 * @brief Deletes power related information for UE
2972 * Function : rgSCHPwrUeDel
2974 * Invoking Module Processing:
2975 * - This shall be invoked by at the time of UE deletion.
2978 * - if (ue->tpcPucchRntiCb)
2979 * - delete UE from tpcPucchRntiCb->ueLst
2980 * - ue->tpcPucchRntiCb = NULLP
2981 * - If in (ue->tpcPucchRntiCb->toBeSchdLst)
2982 * - remove from the list.
2983 * - if (ue->tpcPuschRntiCb)
2984 * - delete UE from tpcPuschRntiCb->ueLst
2985 * - ue->tpcPuschRntiCb = NULLP
2986 * - If in (ue->tpcPuschRntiCb->toBeSchdLst)
2987 * - remove from the list.
2989 * @param[in] RgSchCellCb *cell
2990 * @param[in] RgSchUeCb *ue
2994 PUBLIC Void rgSCHPwrUeDel
3000 PUBLIC Void rgSCHPwrUeDel(cell, ue)
3005 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3006 TRC2(rgSCHPwrUeDel);
3008 if (uePwr->tpcPucchRntiCb)
3010 rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
3011 uePwr->tpcPucchRntiCb = NULLP;
3013 if (uePwr->tpcPuschRntiCb)
3015 rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
3016 uePwr->tpcPuschRntiCb = NULLP;
3022 * @brief Resets UE's power state
3026 * Function : rgSCHPwrUeReset
3028 * Invoking Module Processing:
3029 * - This shall be invoked by at the time PDCCH order.
3032 * - Reset PUSCH power state
3033 * - Reset PUCCH power state
3035 * @param[in] RgSchCellCb *cell
3036 * @param[in] RgSchUeCb *ue
3040 PUBLIC Void rgSCHPwrUeReset
3046 PUBLIC Void rgSCHPwrUeReset(cell, ue)
3051 TRC2(rgSCHPwrUeReset);
3053 rgSCHPwrUeResetPucch(cell, ue);
3054 rgSCHPwrUeResetPusch(cell, ue);
3058 /***********************************************************
3060 * Func : rgSCHPwrUeResetPucch
3062 * Desc : This function is called to reset UE
3063 * to initial PUCCH power state.
3071 **********************************************************/
3073 PRIVATE Void rgSCHPwrUeResetPucch
3079 PRIVATE Void rgSCHPwrUeResetPucch(cell, ue)
3084 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3085 TRC2(rgSCHPwrUeResetPucch);
3087 uePwr->pucchTpc = 1;
3088 uePwr->remPucchPwr = 0;
3089 if (uePwr->tpcPucchRntiCb)
3091 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
3094 /* Stack Crash problem for TRACE5 changes. Added the line below */
3099 /***********************************************************
3101 * Func : rgSCHPwrUeResetPusch
3103 * Desc : This function is called to reset UE
3104 * to initial PUSCH power state.
3112 **********************************************************/
3114 PRIVATE Void rgSCHPwrUeResetPusch
3120 PRIVATE Void rgSCHPwrUeResetPusch(cell, ue)
3125 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3126 TRC2(rgSCHPwrUeResetPusch);
3128 uePwr->isPhrAvail = FALSE;
3130 uePwr->maxUlRbs = RGSCH_MAX_DL_BW;
3132 uePwr->puschTpc = 1;
3133 uePwr->remPuschPwr = 0;
3134 if (uePwr->tpcPuschRntiCb)
3136 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
3141 /***********************************************************
3143 * Func : rgSCHPwrOnPuschPwrUpd
3145 * Desc : This function is called whenever 'remPuschPwr'
3154 **********************************************************/
3156 PRIVATE Void rgSCHPwrOnPuschPwrUpd
3162 PRIVATE Void rgSCHPwrOnPuschPwrUpd(cell, ue)
3167 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3168 RgSchCmnTpcRntiCb *cb;
3170 TRC2(rgSCHPwrOnPuschPwrUpd);
3172 if ((cb = uePwr->tpcPuschRntiCb) == NULLP)
3177 /* Not checking for uwPwr->isPhrAvail as uePwr->phVal
3178 * is set to a large value initially */
3182 if ((uePwr->phVal != 0) && (uePwr->remPuschPwr != 0))
3190 rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue);
3194 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3201 /***********************************************************
3203 * Func : rgSCHPwrAddRntiToPucchRntiLst
3206 * Desc : Adds RNTI to Pucch Rnti list and updates requisite
3211 * Notes: Assumed that array bounds are checked
3212 * in caller before adding.
3216 **********************************************************/
3218 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst
3225 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a)
3231 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3232 TRC2(rgSCHPwrAddRntiToPucchRntiLst);
3234 rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPucchRntiLst[cellPwr->tpcPucchRntiCnt++],
3239 /***********************************************************
3241 * Func : rgSCHPwrAddRntiToPuschRntiLst
3244 * Desc : Adds RNTI to Pusch Rnti list and updates requisite
3249 * Notes: Assumed that array bounds are checked
3250 * in caller before adding.
3254 **********************************************************/
3256 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst
3263 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a)
3269 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3270 TRC2(rgSCHPwrAddRntiToPuschRntiLst);
3272 rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPuschRntiLst[cellPwr->tpcPuschRntiCnt++],
3277 /***********************************************************
3279 * Func : rgSCHPwrInitTpcRntiCb
3282 * Desc : Initialises a TPC RNTI CB
3290 **********************************************************/
3292 PRIVATE Void rgSCHPwrInitTpcRntiCb
3294 RgSchCmnTpcRntiCb *cb,
3299 PRIVATE Void rgSCHPwrInitTpcRntiCb(cb, rnti, isFmt3a)
3300 RgSchCmnTpcRntiCb *cb;
3305 TRC2(rgSCHPwrInitTpcRntiCb);
3307 cmMemset((U8 *)cb, 0, sizeof(*cb));
3309 cb->isFmt3a = isFmt3a;
3310 /* Not initialising lists as memset 0 takes care of it */
3311 /* cb->schdLnk.node is set when this rnti is to be scheduled */
3315 /***********************************************************
3317 * Func : rgSCHPwrGetPucchRntiCb
3320 * Desc : Gets TPC RNTI control block from Pucch rnti list
3322 * Ret : RgSchCmnTpcRntiCb * - Success
3329 **********************************************************/
3331 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb
3337 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb(cell, tpcRnti)
3342 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3344 TRC2(rgSCHPwrGetPucchRntiCb);
3346 if (!cellPwr->tpcPucchRntiCnt)
3350 for (idx = 0; idx < cellPwr->tpcPucchRntiCnt; ++idx)
3352 if (cellPwr->tpcPucchRntiLst[idx].tpcRnti == tpcRnti)
3354 RETVALUE(&cellPwr->tpcPucchRntiLst[idx]);
3360 /***********************************************************
3362 * Func : rgSCHPwrGetPuschRntiCb
3365 * Desc : Gets TPC RNTI control block from Pusch rnti list
3367 * Ret : RgSchCmnTpcRntiCb * - Success
3374 **********************************************************/
3376 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb
3382 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb(cell, tpcRnti)
3387 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3389 TRC2(rgSCHPwrGetPuschRntiCb);
3391 if (!cellPwr->tpcPuschRntiCnt)
3395 for (idx = 0; idx < cellPwr->tpcPuschRntiCnt; ++idx)
3397 if (cellPwr->tpcPuschRntiLst[idx].tpcRnti == tpcRnti)
3399 RETVALUE(&cellPwr->tpcPuschRntiLst[idx]);
3406 /***********************************************************
3408 * Func : rgSCHPwrAddUeToPucchTpcRntiCb
3411 * Desc : Add UE to cfgd list of UEs in rnti cb
3419 **********************************************************/
3421 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb
3424 RgSchCmnTpcRntiCb *cb,
3428 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb(cell, cb, ue)
3430 RgSchCmnTpcRntiCb *cb;
3434 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3436 TRC2(rgSCHPwrAddUeToPucchTpcRntiCb);
3438 cmLListAdd2Tail(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3439 uePwr->pucchGrpLnk.node = (PTR)ue;
3443 /***********************************************************
3445 * Func : rgSCHPwrDelUeFrmPucchTpcRntiCb
3448 * Desc : Remove UE from Pucch TPC RNTI CB
3456 **********************************************************/
3458 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb
3461 RgSchCmnTpcRntiCb *cb,
3465 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, cb, ue)
3467 RgSchCmnTpcRntiCb *cb;
3471 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3472 TRC2(rgSCHPwrDelUeFrmPucchTpcRntiCb);
3474 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
3475 cmLListDelFrm(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3476 uePwr->pucchGrpLnk.node = NULLP;
3480 /***********************************************************
3482 * Func : rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3485 * Desc : Remove UE from to-be-scheduled list of UEs
3494 **********************************************************/
3496 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3499 RgSchCmnTpcRntiCb *cb,
3503 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue)
3505 RgSchCmnTpcRntiCb *cb;
3509 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3510 TRC2(rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb);
3512 if (uePwr->schdPucchGrpLnk.node == NULLP)
3516 rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue);
3517 if (!cb->toBeSchdUes.count)
3519 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
3524 /***********************************************************
3526 * Func : rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3528 * Desc : Remove UE from to-be-scheduled list of UEs
3529 * in Pucch RNTI CB. Do not both about
3530 * possibly removing Pucch RNTI CB from
3531 * the cell wide to-be-scheduled list.
3539 **********************************************************/
3541 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3544 RgSchCmnTpcRntiCb *cb,
3548 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue)
3550 RgSchCmnTpcRntiCb *cb;
3554 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3555 TRC2(rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb);
3557 if (uePwr->schdPucchGrpLnk.node != NULLP)
3559 cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3560 uePwr->schdPucchGrpLnk.node = NULLP;
3565 /***********************************************************
3567 * Func : rgSCHPwrRmvSchdPucchTpcRntiCb
3569 * Desc : Remove Pucch TPC RNTI CB from to-be-scheduled
3578 **********************************************************/
3580 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb
3583 RgSchCmnTpcRntiCb *cb
3586 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb)
3588 RgSchCmnTpcRntiCb *cb;
3591 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3592 TRC2(rgSCHPwrRmvSchdPucchTpcRntiCb);
3594 if (cb->schdLnk.node == NULLP)
3598 cmLListDelFrm(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3599 cb->schdLnk.node = NULLP;
3603 /***********************************************************
3605 * Func : rgSCHPwrAddSchdUeToPucchTpcRntiCb
3607 * Desc : Add UE to to-be-scheduled list of UEs
3616 **********************************************************/
3618 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb
3621 RgSchCmnTpcRntiCb *cb,
3625 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue)
3627 RgSchCmnTpcRntiCb *cb;
3631 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3632 TRC2(rgSCHPwrAddSchdUeToPucchTpcRntiCb);
3634 if (uePwr->schdPucchGrpLnk.node != NULLP)
3636 /* UE is already in the list */
3639 cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3640 uePwr->schdPucchGrpLnk.node = (PTR)ue;
3641 if (cb->toBeSchdUes.count == 1)
3643 /* This is first UE, so queue up this TPC RNTI
3645 rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb);
3650 /***********************************************************
3652 * Func : rgSCHPwrAddSchdPucchTpcRntiCb
3654 * Desc : Add Pucch TPC RNTI CB from to-be-scheduled
3663 **********************************************************/
3665 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb
3668 RgSchCmnTpcRntiCb *cb
3671 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb)
3673 RgSchCmnTpcRntiCb *cb;
3676 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3677 TRC2(rgSCHPwrAddSchdPucchTpcRntiCb);
3679 cmLListAdd2Tail(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3680 cb->schdLnk.node = (PTR)cb;
3685 /***********************************************************
3687 * Func : rgSCHPwrAddUeToPuschTpcRntiCb
3690 * Desc : Add UE to cfgd list of UEs in rnti cb
3698 **********************************************************/
3700 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb
3702 RgSchCmnTpcRntiCb *cb,
3706 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb(cb, ue)
3707 RgSchCmnTpcRntiCb *cb;
3711 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3712 TRC2(rgSCHPwrAddUeToPuschTpcRntiCb);
3714 cmLListAdd2Tail(&cb->cfgdUes, &uePwr->puschGrpLnk);
3715 uePwr->puschGrpLnk.node = (PTR)ue;
3719 /***********************************************************
3721 * Func : rgSCHPwrAddSchdUeToPuschTpcRntiCb
3723 * Desc : Add UE to to-be-scheduled list of UEs
3732 **********************************************************/
3734 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb
3737 RgSchCmnTpcRntiCb *cb,
3741 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue)
3743 RgSchCmnTpcRntiCb *cb;
3747 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3748 TRC2(rgSCHPwrAddSchdUeToPuschTpcRntiCb);
3750 if (uePwr->schdPuschGrpLnk.node != NULLP)
3752 /* UE is already in the list */
3755 cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3756 uePwr->schdPuschGrpLnk.node = (PTR)ue;
3757 if (cb->toBeSchdUes.count == 1)
3759 /* This is first UE, so queue up this TPC RNTI
3761 rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb);
3766 /***********************************************************
3768 * Func : rgSCHPwrDelUeFrmPuschTpcRntiCb
3771 * Desc : Add UE to cfgd list of UEs in rnti cb
3779 **********************************************************/
3781 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb
3784 RgSchCmnTpcRntiCb *cb,
3788 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, cb, ue)
3790 RgSchCmnTpcRntiCb *cb;
3794 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3795 TRC2(rgSCHPwrDelUeFrmPuschTpcRntiCb);
3797 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3798 cmLListDelFrm(&cb->cfgdUes, &uePwr->puschGrpLnk);
3799 uePwr->puschGrpLnk.node = NULLP;
3803 /***********************************************************
3805 * Func : rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3807 * Desc : Remove UE from to-be-scheduled list of UEs
3816 **********************************************************/
3818 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3821 RgSchCmnTpcRntiCb *cb,
3825 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue)
3827 RgSchCmnTpcRntiCb *cb;
3831 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3832 TRC2(rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb);
3834 if (uePwr->schdPuschGrpLnk.node == NULLP)
3838 rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue);
3839 if (!cb->toBeSchdUes.count)
3841 rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
3846 /***********************************************************
3848 * Func : rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3850 * Desc : Remove UE from to-be-scheduled list of UEs
3851 * in Pusch RNTI CB. Do not both about
3852 * possibly removing Pusch RNTI CB from
3853 * the cell wide to-be-scheduled list.
3861 **********************************************************/
3863 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3866 RgSchCmnTpcRntiCb *cb,
3870 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue)
3872 RgSchCmnTpcRntiCb *cb;
3876 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3877 TRC2(rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb);
3879 if (uePwr->schdPuschGrpLnk.node != NULLP)
3881 cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3882 uePwr->schdPuschGrpLnk.node = NULLP;
3887 /***********************************************************
3889 * Func : rgSCHPwrAddSchdPuschTpcRntiCb
3891 * Desc : Add Pusch TPC RNTI CB from to-be-scheduled
3900 **********************************************************/
3902 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb
3905 RgSchCmnTpcRntiCb *cb
3908 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb)
3910 RgSchCmnTpcRntiCb *cb;
3913 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3914 TRC2(rgSCHPwrAddSchdPuschTpcRntiCb);
3916 cmLListAdd2Tail(&cellPwr->puschGrpPwr, &cb->schdLnk);
3917 cb->schdLnk.node = (PTR)cb;
3921 /***********************************************************
3923 * Func : rgSCHPwrRmvSchdPuschTpcRntiCb
3925 * Desc : Remove Pusch TPC RNTI CB from to-be-scheduled
3934 **********************************************************/
3936 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb
3939 RgSchCmnTpcRntiCb *cb
3942 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb)
3944 RgSchCmnTpcRntiCb *cb;
3947 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3948 TRC2(rgSCHPwrRmvSchdPuschTpcRntiCb);
3950 if (cb->schdLnk.node == NULLP)
3954 cmLListDelFrm(&cellPwr->puschGrpPwr, &cb->schdLnk);
3955 cb->schdLnk.node = NULLP;
3959 /***********************************************************
3961 * Func : rgSCHPwrChkPucchTpcRntiIdx
3963 * Desc : Validate that the given index is OK to
3964 * be assigned to a new UE for the Pucch TPC
3973 **********************************************************/
3975 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx
3977 RgSchCmnTpcRntiCb *cb,
3981 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx(cb, idx)
3982 RgSchCmnTpcRntiCb *cb;
3986 TRC2(rgSCHPwrChkPucchTpcRntiIdx);
3988 if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3992 if (rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx) != ROK)
3999 /***********************************************************
4001 * Func : rgSCHPwrChkPuschTpcRntiIdx
4003 * Desc : Validate that the given index is OK to
4004 * be assigned to a new UE for the Pusch TPC
4013 **********************************************************/
4015 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx
4017 RgSchCmnTpcRntiCb *cb,
4021 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx(cb, idx)
4022 RgSchCmnTpcRntiCb *cb;
4026 TRC2(rgSCHPwrChkPuschTpcRntiIdx);
4028 if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
4032 if (rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx) != ROK)
4039 /***********************************************************
4041 * Func : rgSCHPwrChkUniqPucchTpcRntiIdx
4043 * Desc : Validate index against format type of TPC RNTI
4051 **********************************************************/
4053 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx
4055 RgSchCmnTpcRntiCb *cb,
4059 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx)
4060 RgSchCmnTpcRntiCb *cb;
4065 TRC2(rgSCHPwrChkUniqPucchTpcRntiIdx);
4067 for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
4069 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
4070 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
4071 if (uePwr->pucchIdx == idx)
4079 /***********************************************************
4081 * Func : rgSCHPwrChkUniqPuschTpcRntiIdx
4083 * Desc : Validate index against format type of TPC RNTI
4091 **********************************************************/
4093 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx
4095 RgSchCmnTpcRntiCb *cb,
4099 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx)
4100 RgSchCmnTpcRntiCb *cb;
4105 TRC2(rgSCHPwrChkUniqPuschTpcRntiIdx);
4107 for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
4109 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
4110 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
4111 if (uePwr->puschIdx == idx)
4119 /***********************************************************
4121 * Func : rgSCHPwrChkTpcRntiIdx
4123 * Desc : Validate index against format type of TPC RNTI.
4131 **********************************************************/
4133 PRIVATE S16 rgSCHPwrChkTpcRntiIdx
4135 RgSchCmnTpcRntiCb *cb,
4139 PRIVATE S16 rgSCHPwrChkTpcRntiIdx(cb, idx)
4140 RgSchCmnTpcRntiCb *cb;
4144 TRC2(rgSCHPwrChkTpcRntiIdx);
4148 if (idx >= TFU_MAX_1BIT_TPC)
4155 if (idx >= TFU_MAX_2BIT_TPC)
4162 /* Warning Fix: Commenting out as not used */
4164 /***********************************************************
4166 * Func : rgSCHPwrGetPCMaxValFromPCMax
4168 * Desc : Returns the power headroom in dB
4169 * corresponding to a power headroom
4178 **********************************************************/
4180 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax
4185 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax(pCMax)
4189 TRC2(rgSCHPwrGetPCMaxValFromPCMax);
4190 RETVALUE((pCMax & 63) - 30);
4195 /***********************************************************
4197 * Func : rgSCHPwrGetPhValFromPhr
4199 * Desc : Returns the power headroom in dB
4200 * corresponding to a power headroom
4209 **********************************************************/
4211 PRIVATE S8 rgSCHPwrGetPhValFromPhr
4216 PRIVATE S8 rgSCHPwrGetPhValFromPhr(phr)
4220 TRC2(rgSCHPwrGetPhValFromPhr);
4221 RETVALUE((phr & 63) - 23);
4226 /**********************************************************************
4229 **********************************************************************/