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 "common_def.h"
45 #include "rg_sch_inf.h"
46 #include "rg_sch_err.h"
48 #include "rg_sch_cmn.h"
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"
62 /* Current specs have 23 dBm as max tx power capability for UEs */
63 #define RG_SCH_PWR_UE_MAX_PWR 23
65 #define RG_SCH_REF_PCMAX 0xFF
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
74 typedef S8 RgSchCmnUlPwrCqiToPwrTbl[RG_SCH_CMN_UL_NUM_CQI];
76 PRIVATE RgSchCmnUlPwrCqiToPwrTbl rgSchPwrCqiToPwrTbl;
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 CONSTANT U8 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
95 /* This table maps power (in dB) to number of RBs */
96 /* The array size comes from max power in rgSchPwrRbToPwrTbl */
97 CONSTANT U8 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
104 PRIVATE S8 rgSCHPwrGetCqiPwr ARGS((
107 PRIVATE S8 rgSCHPwrGetCqiPwrForUe ARGS((
112 PRIVATE S8 rgSCHPwrCalcEfficncyPwr ARGS((
115 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi ARGS((
121 PRIVATE Void rgSCHPwrGetPuschTpc ARGS((
128 PRIVATE U8 rgSCHPwrGetMaxRb ARGS((
132 PRIVATE U8 rgSCHPwrRbToPwr ARGS((
136 PRIVATE Void rgSCHPwrSchedPucchRnti ARGS((
138 RgSchCmnTpcRntiCb *cb,
143 PRIVATE Void rgSCHPwrPuschCntrl ARGS((
147 PRIVATE Void rgSCHPwrPucchCntrl ARGS((
151 PRIVATE Void rgSCHPwrSchedPuschRnti ARGS((
153 RgSchCmnTpcRntiCb *cb,
158 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe ARGS((
163 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe ARGS((
168 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe ARGS((
173 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe ARGS((
178 PRIVATE Void rgSCHPwrGetAcc1bitTpc ARGS((
183 PRIVATE Void rgSCHPwrGetAcc2bitTpc ARGS((
188 PRIVATE Void rgSCHPwrGetAbsTpc ARGS((
193 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe ARGS((
198 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe ARGS((
203 PRIVATE Bool rgSCHPwrIsDlUeSched ARGS((
208 PRIVATE Bool rgSCHPwrIsUlUeSched ARGS((
213 PRIVATE Void rgSCHPwrOnSchedPucchTpc ARGS((
218 PRIVATE Void rgSCHPwrOnSchedPuschTpc ARGS((
222 PRIVATE S16 rgSCHPwrApplyUePwrCfg ARGS((
225 RgrUeUlPwrCfg *pwrCfg
227 PRIVATE Void rgSCHPwrUeResetPucch ARGS((
231 PRIVATE Void rgSCHPwrUeResetPusch ARGS((
235 PRIVATE Void rgSCHPwrOnPuschPwrUpd ARGS((
239 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst ARGS((
244 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst ARGS((
249 PRIVATE Void rgSCHPwrInitTpcRntiCb ARGS((
250 RgSchCmnTpcRntiCb *cb,
254 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb ARGS((
258 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb ARGS((
262 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb ARGS((
264 RgSchCmnTpcRntiCb *cb,
267 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb ARGS((
269 RgSchCmnTpcRntiCb *cb,
272 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb ARGS((
274 RgSchCmnTpcRntiCb *cb,
277 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb ARGS((
279 RgSchCmnTpcRntiCb *cb,
282 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb ARGS((
284 RgSchCmnTpcRntiCb *cb
286 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb ARGS((
288 RgSchCmnTpcRntiCb *cb,
291 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb ARGS((
293 RgSchCmnTpcRntiCb *cb
295 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb ARGS((
296 RgSchCmnTpcRntiCb *cb,
299 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb ARGS((
301 RgSchCmnTpcRntiCb *cb,
304 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb ARGS((
306 RgSchCmnTpcRntiCb *cb,
309 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb ARGS((
311 RgSchCmnTpcRntiCb *cb,
314 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb ARGS((
316 RgSchCmnTpcRntiCb *cb,
319 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb ARGS((
321 RgSchCmnTpcRntiCb *cb
323 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb ARGS((
325 RgSchCmnTpcRntiCb *cb
327 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx ARGS((
328 RgSchCmnTpcRntiCb *cb,
331 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx ARGS((
332 RgSchCmnTpcRntiCb *cb,
335 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx ARGS((
336 RgSchCmnTpcRntiCb *cb,
339 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx ARGS((
340 RgSchCmnTpcRntiCb *cb,
343 PRIVATE S16 rgSCHPwrChkTpcRntiIdx ARGS((
344 RgSchCmnTpcRntiCb *cb,
347 PRIVATE S8 rgSCHPwrGetPhValFromPhr ARGS((
350 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax ARGS((
358 * @brief Does power related initialisation (not cell specific).
363 * Function : rgSCHPwrInit
366 * - This shall precompute coding efficiency to power
367 * mappings (assuming beta of 1).
372 PUBLIC Void rgSCHPwrInit
377 PUBLIC Void rgSCHPwrInit()
383 rgSchPwrCqiToPwrTbl[0] = 0; /* This should never be used anyway */
384 for (idx = 1; idx < RG_SCH_CMN_UL_NUM_CQI; ++idx)
386 rgSchPwrCqiToPwrTbl[idx] = rgSCHPwrCalcEfficncyPwr(rgSchCmnUlCqiTbl[idx].eff);
391 /***********************************************************
393 * Func : rgSCHPwrGetCqiPwr
395 * Desc : Returns power corresponding to coding efficiency
396 * when beta pusch is assumed 1.
404 **********************************************************/
406 PRIVATE S8 rgSCHPwrGetCqiPwr
411 PRIVATE S8 rgSCHPwrGetCqiPwr(cqi)
415 TRC2(rgSCHPwrGetCqiPwr);
417 return (rgSchPwrCqiToPwrTbl[cqi]);
418 } /* rgSCHPwrGetCqiPwr */
420 /***********************************************************
422 * Func : rgSCHPwrGetCqiPwrForUe
424 * Desc : If MCS control is enabled for UE, returns
425 * power corresponding to CQI, else 0.
433 **********************************************************/
435 PRIVATE S8 rgSCHPwrGetCqiPwrForUe
442 PRIVATE S8 rgSCHPwrGetCqiPwrForUe(cell, ue, cqi)
448 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
449 TRC2(rgSCHPwrGetCqiPwrForUe);
451 if (!uePwr->deltaMcsEnbld)
455 return (rgSCHPwrGetCqiPwr(cqi));
456 } /* rgSCHPwrGetCqiPwrForUe */
458 /***********************************************************
460 * Func : rgSCHPwrCalcEfficncyPwr
462 * Desc : Computes power corresponding to a coding
467 * Notes: Assumes beta pusch to be 1
471 **********************************************************/
473 PRIVATE S8 rgSCHPwrCalcEfficncyPwr
478 PRIVATE S8 rgSCHPwrCalcEfficncyPwr(eff)
482 F64 ks = 1.25; /* or F64 */
483 F64 tmp = cmPow(2, ks*eff/1024) - 1;
484 TRC2(rgSCHPwrCalcEfficncyPwr);
488 return ((S8)(10 * cmLog10(tmp)));
489 } /* rgSCHPwrCalcEfficncyPwr */
493 * @brief Returns TPC to be sent in UL allocation
497 * Function : rgSCHPwrPuschTpcForUe
499 * Invoking Module Processing:
500 * - After allocation for UE, this function shall
501 * be invoked to retrieve TPC.
502 * - This assumes that rgSCHPwrGetMaxUlRb() was
503 * invoked prior to final allocation for UE.
506 * - Just return TPC that was determined
508 * - After this, do necessary updates.
510 * @param[in] RgSchCellCb *cell
511 * @param[in] RgSchUeCb *ue
515 PUBLIC U8 rgSCHPwrPuschTpcForUe
521 PUBLIC U8 rgSCHPwrPuschTpcForUe(cell, ue)
526 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue,cell);
529 TRC2(rgSCHPwrPuschTpcForUe);
531 rgSCHPwrOnSchedPuschTpc(cell, ue);
532 return (uePwr->puschTpc);
536 * @brief Handles Pusch power control for DCI format 0
540 * Function : rgSCHPwrGetMaxUlRb
542 * Invoking Module Processing:
543 * - This shall be invoked to determine maximum
544 * number of UL RBs for scheduling.
545 * - This is expected to be invoked every time
546 * priority to attempt at UE allocation. Later
547 * TPC retrieval depends on it.
550 * - Returns maximum allowed UL RBs to be granted
551 * after invoking Pusch power control.
553 * @param[in] RgSchCellCb *cell
554 * @param[in] RgSchUeCb *ue
558 PUBLIC U8 rgSCHPwrGetMaxUlRb
564 PUBLIC U8 rgSCHPwrGetMaxUlRb(cell, ue)
569 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
570 TRC2(rgSCHPwrGetMaxUlRb);
572 rgSCHPwrPuschCntrl(cell, ue); /* This stores tpc, delta and maxRb
574 return (uePwr->maxUlRbs);
578 * @brief Handles Pusch power control for DCI format 0
582 * Function : rgSCHPwrPuschCntrl
584 * Invoking Module Processing:
585 * - This shall be invoked to determine TPC
586 * and maximum number of UL RBs for scheduling
587 * (through DCI format 0).
590 * - 'remPuschPwr' is the final delta power that the UE
591 * should apply to get to target CQI.
592 * - The available headroom (availPwr) is determined.
593 * - Power command is given by considering remPuschPwr and
595 * - After factoring in the power command into availPwr, the
596 * maximum number of RBs that can be supported is determined
597 * assuming that UE is going to use transmission efficiency
598 * corresponding to current CQI.
599 * - The results determined in this function are stored
600 * in the UE power control block.
601 * - [Not doing anything of power control of msg3
602 * retransmissions now]
604 * @param[in] RgSchCellCb *cell
605 * @param[in] RgSchUeCb *ue
609 PRIVATE Void rgSCHPwrPuschCntrl
615 PRIVATE Void rgSCHPwrPuschCntrl(cell, ue)
620 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
621 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
622 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
625 U8 cqi = ueUl->validUlCqi;
628 U8 cqi = ueUl->crntUlCqi[0];
630 Bool isAcc = uePwr->isAccumulated;
637 TRC2(rgSCHPwrPuschCntrl);
639 if (!uePwr->isPhrAvail)
641 availPwr = 60; /* setting a large value so that availPwr does
642 * not constrain delta */
646 availPwr = uePwr->maxUePwr - uePwr->pwrPerRb;
647 availPwr -= rgSCHPwrGetCqiPwrForUe(cell, ue, cqi);
649 delta = uePwr->remPuschPwr;
650 rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, &tpc, &delta);
653 maxRb = rgSCHPwrGetMaxRb(cell,availPwr);
655 /* Store the results in ue power control block to be used later */
656 if(maxRb < cellUl->sbSize)
658 maxRb = cellUl->sbSize;
660 if(uePwr->maxPwrDeltaByPhr < 0)
662 tmp = ueUl->validUlCqi;
663 tmp = tmp + uePwr->maxPwrDeltaByPhr;
666 ueUl->validUlCqi = 1;
670 ueUl->validUlCqi = tmp;
675 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
676 "UEID:%d Output Max Rb (%d), phVal (%d) AvailPwr (%d) ",
677 ue->ueId, maxRb, uePwr->phVal, availPwr);
678 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
679 "UEID:%d pwrPerRb %d remPuschPwr %d",
683 uePwr->delta = delta;
684 uePwr->maxUlRbs = maxRb;
685 uePwr->puschTpc = tpc;
690 * @brief Returns TPC to be sent in DL allocation
694 * Function : rgSCHPwrPucchTpcForUe
696 * Invoking Module Processing:
697 * - After DL allocation for UE, this function shall
698 * be invoked to obtain TPC.
701 * - Do Pucch power control processing
704 * @param[in] RgSchCellCb *cell
705 * @param[in] RgSchUeCb *ue
709 PUBLIC U8 rgSCHPwrPucchTpcForUe
715 PUBLIC U8 rgSCHPwrPucchTpcForUe(cell, ue)
720 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
721 TRC2(rgSCHPwrPucchTpcForUe);
723 rgSCHPwrPucchCntrl(cell, ue);
724 return (uePwr->pucchTpc);
727 /***********************************************************
729 * Func : rgSCHPwrGetDelta2FrmCqi
731 * Desc : Get power to be applied to achieve
732 * target CQI (the power returned is
733 * twice is actual power)
741 **********************************************************/
743 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi
752 PRIVATE S8 rgSCHPwrGetDelta2FrmCqi(crntCqi, trgCqi)
759 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
760 TRC2(rgSCHPwrGetDelta2FrmCqi);
762 if (uePwr->isPhrAvail)
764 //uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb - uePwr->remPuschPwr;
765 uePwr->maxPwrDeltaByPhr = uePwr->maxPwrPerRb - uePwr->pwrPerRb;
769 uePwr->maxPwrDeltaByPhr = 0;
772 if (uePwr->maxPwrDeltaByPhr < 0 && (trgCqi - crntCqi) *
773 RG_SCH_UL_CQI_DB_STEP_2 > 0)
777 return (RGSCH_MIN(uePwr->maxPwrDeltaByPhr,
778 (trgCqi - crntCqi) * RG_SCH_UL_CQI_DB_STEP_2));
779 } /* rgSCHPwrGetDelta2FrmCqi */
781 /***********************************************************
783 * Func : rgSCHPwrGetPuschTpc
785 * Desc : Based on whether accumulation is enabled or
786 * not, this returns an applicable power delta
787 * to be applied based on the input delta.
795 **********************************************************/
797 PRIVATE Void rgSCHPwrGetPuschTpc
806 PRIVATE Void rgSCHPwrGetPuschTpc(isAcc, delta, availPwr, tpc, tpcDelta)
814 TRC2(rgSCHPwrGetPuschTpc);
816 delta = RGSCH_MIN(delta, availPwr);
818 /* As of now, the functions below possibly cause delta
819 * to be breached by 1 only. So calling these as is. */
822 rgSCHPwrGetAcc2bitTpc(delta, tpc, tpcDelta);
826 rgSCHPwrGetAbsTpc(delta, tpc, tpcDelta);
829 } /* rgSCHPwrGetPuschTpc */
831 /***********************************************************
833 * Func : rgSCHPwrGetMaxRb
835 * Desc : Get the maximum number of RBs that can be
836 * expected to be supported by the passed
845 **********************************************************/
847 PRIVATE U8 rgSCHPwrGetMaxRb
853 PRIVATE U8 rgSCHPwrGetMaxRb(cell, pwr)
858 RgSchCmnUlCell *cellUl;
860 TRC2(rgSCHPwrGetMaxRb);
862 cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
865 /* Give 4 RBS so that UE can report changed power status*/
866 /* [ccpu00119916] Mod -return 0th index of rgSchPwrToRbTbl when pwr <=0
867 * Change the Macros from RGSCH_MAX_DL_BW to RGSCH_MAX_UL_BW*/
868 return (rgSchPwrToRbTbl[0]);
870 if (pwr > rgSchPwrRbToPwrTbl[cellUl->maxUlBwPerUe])
872 return (cellUl->maxUlBwPerUe);
874 return (RGSCH_MIN(cellUl->maxUlBwPerUe,rgSchPwrToRbTbl[(U8)pwr]));
875 } /* rgSCHPwrGetMaxRb */
877 /***********************************************************
879 * Func : rgSCHPwrRbToPwr
881 * Desc : Get the power corresponding to number of RBs
889 **********************************************************/
891 PRIVATE U8 rgSCHPwrRbToPwr
897 PRIVATE U8 rgSCHPwrRbToPwr(cell,numRb)
903 RgSchCmnUlCell *cellUl;
905 TRC2(rgSCHPwrRbToPwr);
906 #if (ERRCLASS & ERRCLS_DEBUG)
907 cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
908 if (numRb > cellUl->maxUlBwPerUe)
910 numRb = cellUl->maxUlBwPerUe;
913 return (rgSchPwrRbToPwrTbl[numRb]);
914 } /* rgSCHPwrRbToPwr */
918 * @brief Handles Pucch power control for DCI formats 1A/1B/1D/1/2A/2
922 * Function : rgSCHPwrPucchCntrl
925 * - Determine 2 bit TPC to be sent using remPucchPwr.
926 * - Update remPucchPwr appropriately
928 * @param[in] RgSchCellCb *cell
929 * @param[in] RgSchUeCb *ue
933 PRIVATE Void rgSCHPwrPucchCntrl
939 PRIVATE Void rgSCHPwrPucchCntrl(cell, ue)
945 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
946 TRC2(rgSCHPwrPucchCntrl);
948 rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, &uePwr->pucchTpc, &delta);
949 rgSCHPwrOnSchedPucchTpc(cell, ue, delta);
954 * @brief Handles group power control for DCI formats 3/3A for Pucch and Pusch
958 * Function : rgSCHPwrGrpCntrlPucch
960 * Invoking Module Processing:
961 * - This shall be invoked to do group power control for
962 * all TPC RNTIs for which it is deemed necessary to
963 * do the same (group power control).
964 * - This function should only be invoked after all UEs
965 * have been scheduled for uplink (re)transmissions
966 * requiring DL DCI format in the passed subframe.
969 * - For Pucch group power control
970 * - For each TPC-Pucch-RNTI in the pucchGrpPwr List and
971 * TPC-Pusch-RNTI in the puschGrpPwr List,
972 * - Request for PDCCH, skip if not available
973 * - Form DCI format 3/3A information depending
974 * on the format type of the TPC-RNTI and add it to the sub-frame.
975 * - For each Ue in ueLst of TPC RNTI Cb
976 * - if (fmtType == 3A)
977 * - if((Ue not scheduled DL dci formats)
978 * && (remPwr >= 2 || remPwr <= -2))
979 * - Determine TPC. Set puschTpc/pucchTpc.
981 * - if (remPwr >= -1 && remPwr <= 1)
982 * - If already added, remove from toBeSchdLst
984 * - Toggle the remainig power value
985 * - else if (fmtType == 3)
986 * - if((Ue not scheduled DL dci formats)
988 * - Determine TPC. Set puschTpc/pucchTpc.
991 * - If already added, remove from toBeSchdLst
992 * - if (!toBeSchdUeCnt)
993 * - Remove the tpcRntiCb frm pucchGrpPwr/puschGrpPwr List
994 * - else, Move the tpcRntiCb to end of the list (not doing
997 * @param[in] RgSchCellCb *cell
998 * @param[in] RgSchDlSf *dlSf
1002 PUBLIC Void rgSCHPwrGrpCntrlPucch
1008 PUBLIC Void rgSCHPwrGrpCntrlPucch(cell, dlSf)
1013 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
1017 TRC2(rgSCHPwrGrpCntrlPucch);
1019 lst = &cellPwr->pucchGrpPwr;
1021 while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1023 RgSchCmnTpcRntiCb *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1026 rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, &sched);
1029 rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1031 /* TPC RNTI would not have been removed if needs to
1032 * be scheduled again */
1039 * @brief Handles group power control for DCI formats 3/3A for Pusch and Pusch
1043 * Function : rgSCHPwrGrpCntrlPusch
1045 * Invoking Module Processing:
1046 * - This shall be invoked to do group power control for
1047 * all TPC RNTIs for which it is deemed necessary to
1048 * do the same (group power control).
1049 * - This function should only be invoked after all UEs
1050 * have been scheduled for uplink (re)transmissions
1051 * requiring DCI format 0 in the passed subframe.
1054 * - For Pusch group power control
1055 * - For each TPC-Pusch-RNTI in the puschGrpPwr List and
1056 * - Request for PDCCH, skip if not available
1057 * - Form DCI format 3/3A information depending
1058 * on the format type of the TPC-RNTI and add it to the sub-frame.
1059 * - For each Ue in ueLst of TPC RNTI Cb
1060 * - if (fmtType == 3A)
1061 * - if (Ue not scheduled for dci format 0) and
1062 * (remPwr >= 2 || remPwr <= -2))
1063 * - Determine TPC. Set puschTpc/puschTpc.
1065 * - if (remPwr >= -1 && remPwr <= 1)
1066 * - If already added, remove from toBeSchdLst
1068 * - Toggle the remainig power value
1069 * - else if (fmtType == 3)
1070 * - if((Ue not scheduled for dci format 0) && (remPwr))
1071 * - Determine TPC. Set puschTpc.
1074 * - If already added, remove from toBeSchdLst
1075 * - if (!toBeSchdUeCnt)
1076 * - Remove the tpcRntiCb frm puschGrpPwr/puschGrpPwr List
1077 * - else, Move the tpcRntiCb to end of the list (not doing
1080 * @param[in] RgSchCellCb *cell
1081 * @param[in] RgSchDlSf *sf
1085 PUBLIC Void rgSCHPwrGrpCntrlPusch
1092 PUBLIC Void rgSCHPwrGrpCntrlPusch(cell, dlSf, ulSf)
1098 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
1102 TRC2(rgSCHPwrGrpCntrlPusch);
1104 lst = &cellPwr->puschGrpPwr;
1106 while (lnk && ((pdcch = rgSCHCmnCmnPdcchAlloc(cell, dlSf)) != NULLP))
1108 RgSchCmnTpcRntiCb *cb = (RgSchCmnTpcRntiCb *)lnk->node;
1111 rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, &sched);
1114 rgSCHUtlPdcchPut(cell, &dlSf->pdcchInfo, pdcch);
1116 /* TPC RNTI would not have been removed if needs to
1117 * be scheduled again */
1123 /***********************************************************
1125 * Func : rgSCHPwrSchedPucchRnti
1127 * Desc : Schedule TPC RNTI to be sent out
1135 **********************************************************/
1137 PRIVATE Void rgSCHPwrSchedPucchRnti
1140 RgSchCmnTpcRntiCb *cb,
1146 PRIVATE Void rgSCHPwrSchedPucchRnti(cell, cb, pdcch, dlSf, sched)
1148 RgSchCmnTpcRntiCb *cb;
1160 TRC2(rgSCHPwrSchedPucchRnti);
1162 pdcch->rnti = cb->tpcRnti;
1166 /* Go through all UEs for format 3A case */
1168 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1169 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1170 pdcch->dci.u.format3AInfo.isPucch = TRUE;
1172 tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1173 /* No need to memset zero initially as every TPC is going
1174 * to be filled up for every configured UE */
1175 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1177 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1178 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1180 if ( ue->isDrxEnabled == TRUE &&
1181 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1183 /* UE is in its DRX time. So we cannot give command
1189 if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1191 /* UE already scheduled in downlink with PDCCH
1192 * carrying PUCCH pwr cmd. So don't care about
1193 * giving command to this UE. */
1196 rgSCHPwrGetPucchFmt3aTpcForUe(ue, &tpc, &delta);
1197 tpcCmds[uePwr->pucchIdx] = tpc;
1199 rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1204 /* Go through to-be-scheduled UEs for format 3 case */
1205 lst = &cb->toBeSchdUes;
1206 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1207 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1208 tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1209 pdcch->dci.u.format3Info.isPucch = TRUE;
1211 /* Fill TPC 1 (corresponding to no power change) initially */
1212 cmMemset((U8 *)tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1214 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1216 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1217 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1219 if ( ue->isDrxEnabled == TRUE &&
1220 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1222 /* UE is in its DRX time. So we cannot give command
1228 if (rgSCHPwrIsDlUeSched(cell, ue, dlSf))
1230 /* UE already scheduled in downlink with PDCCH
1231 * carrying PUCCH pwr cmd. So don't care about
1232 * giving command to this UE. */
1235 rgSCHPwrGetPucchFmt3TpcForUe(ue, &tpc, &delta);
1236 tpcCmds[uePwr->pucchIdx] = tpc;
1238 rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta);
1242 *sched = atleastOne;
1244 /* Check if no more UEs in TPC RNTI, and then remove
1245 * this TPC RNTI from scheduled list */
1246 if (cb->toBeSchdUes.count == 0)
1248 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
1252 } /* rgSCHPwrSchedPucchRnti */
1254 /***********************************************************
1256 * Func : rgSCHPwrSchedPuschRnti
1258 * Desc : Schedule TPC RNTI to be sent out
1266 **********************************************************/
1268 PRIVATE Void rgSCHPwrSchedPuschRnti
1271 RgSchCmnTpcRntiCb *cb,
1277 PRIVATE Void rgSCHPwrSchedPuschRnti(cell, cb, pdcch, ulSf, sched)
1279 RgSchCmnTpcRntiCb *cb;
1291 TRC2(rgSCHPwrSchedPuschRnti);
1293 pdcch->rnti = cb->tpcRnti;
1297 /* Go through all UEs for format 3A case */
1299 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3A;
1300 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3A];
1301 pdcch->dci.u.format3AInfo.isPucch = FALSE;
1302 tpcCmds = pdcch->dci.u.format3AInfo.tpcCmd;
1303 /* No need to memset zero initially as every TPC is going
1304 * to be filled up for every configured UE */
1305 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1307 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1308 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1309 if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1311 /* UE already scheduled in uplink with DCI
1312 * format 0. So don't care about giving
1313 * command to this UE. */
1317 if ( ue->isDrxEnabled == TRUE &&
1318 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1320 /* UE is in its DRX time. So we cannot give command
1326 rgSCHPwrGetPuschFmt3aTpcForUe(ue, &tpc, &delta);
1327 tpcCmds[uePwr->puschIdx] = tpc;
1329 rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1334 /* Go through to-be-scheduled UEs for format 3 case */
1335 lst = &cb->toBeSchdUes;
1336 pdcch->dci.dciFormat = TFU_DCI_FORMAT_3;
1337 pdcch->dciNumOfBits = cell->dciSize.size[TFU_DCI_FORMAT_3];
1338 pdcch->dci.u.format3Info.isPucch = FALSE;
1339 tpcCmds = pdcch->dci.u.format3Info.tpcCmd;
1341 /* Fill TPC 1 (corresponding to no power change) initially */
1342 cmMemset((U8 *)tpcCmds, 1, sizeof(pdcch->dci.u.format3Info.tpcCmd));
1344 for (atleastOne = FALSE, lnk = lst->first; lnk; lnk = lnk->next)
1346 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
1347 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1348 if (rgSCHPwrIsUlUeSched(cell, ue, ulSf))
1350 /* UE already scheduled in uplink with DCI
1351 * format 0. So don't care about giving
1352 * command to this UE. */
1356 if ( ue->isDrxEnabled == TRUE &&
1357 !RG_SCH_DRX_DL_IS_UE_ACTIVE(ue->drxCb))
1359 /* UE is in its DRX time. So we cannot give command
1365 rgSCHPwrGetPuschFmt3TpcForUe(ue, &tpc, &delta);
1366 tpcCmds[uePwr->puschIdx] = tpc;
1368 rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta);
1372 *sched = atleastOne;
1374 /* Check if no more UEs in TPC RNTI, and then remove
1375 * this TPC RNTI from scheduled list */
1376 if (cb->toBeSchdUes.count == 0)
1378 rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
1382 } /* rgSCHPwrSchedPuschRnti */
1384 /***********************************************************
1386 * Func : rgSCHPwrGetPucchFmt3TpcForUe
1388 * Desc : Gets 2 bit TPC cmd for PUCCH
1396 **********************************************************/
1398 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe
1405 PRIVATE Void rgSCHPwrGetPucchFmt3TpcForUe(ue, tpc, delta)
1411 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1412 TRC2(rgSCHPwrGetPucchFmt3TpcForUe);
1414 rgSCHPwrGetAcc2bitTpc(uePwr->remPucchPwr, tpc, delta);
1416 } /* rgSCHPwrGetPucchFmt3TpcForUe */
1418 /***********************************************************
1420 * Func : rgSCHPwrGetPucchFmt3aTpcForUe
1422 * Desc : Gets 1 bit TPC cmd for PUCCH
1430 **********************************************************/
1432 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe
1439 PRIVATE Void rgSCHPwrGetPucchFmt3aTpcForUe(ue, tpc, delta)
1445 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1446 TRC2(rgSCHPwrGetPucchFmt3aTpcForUe);
1448 rgSCHPwrGetAcc1bitTpc(uePwr->remPucchPwr, tpc, delta);
1450 } /* rgSCHPwrGetPucchFmt3aTpcForUe */
1452 /***********************************************************
1454 * Func : rgSCHPwrGetPuschFmt3TpcForUe
1456 * Desc : Gets 2 bit TPC cmd for PUCCH
1464 **********************************************************/
1466 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe
1473 PRIVATE Void rgSCHPwrGetPuschFmt3TpcForUe(ue, tpc, delta)
1479 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1480 S8 adj = RGSCH_MIN(uePwr->remPuschPwr, uePwr->phVal);
1481 TRC2(rgSCHPwrGetPuschFmt3TpcForUe);
1483 rgSCHPwrGetAcc2bitTpc(adj, tpc, delta);
1485 } /* rgSCHPwrGetPuschFmt3TpcForUe */
1487 /***********************************************************
1489 * Func : rgSCHPwrGetPuschFmt3aTpcForUe
1491 * Desc : Gets 1 bit TPC cmd for PUCCH
1499 **********************************************************/
1501 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe
1508 PRIVATE Void rgSCHPwrGetPuschFmt3aTpcForUe(ue, tpc, delta)
1514 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1515 TRC2(rgSCHPwrGetPuschFmt3aTpcForUe);
1517 /* Don't attempt to look at headroom now, power
1518 * adjustment is small anyway */
1519 rgSCHPwrGetAcc1bitTpc(uePwr->remPuschPwr, tpc, delta);
1521 } /* rgSCHPwrGetPuschFmt3aTpcForUe */
1523 /***********************************************************
1525 * Func : rgSCHPwrGetAcc1bitTpc
1527 * Desc : Gets 1 bit TPC cmd
1535 **********************************************************/
1537 PRIVATE Void rgSCHPwrGetAcc1bitTpc
1544 PRIVATE Void rgSCHPwrGetAcc1bitTpc(remPwr, tpc, delta)
1550 TRC2(rgSCHPwrGetAcc1bitTpc);
1567 } /* rgSCHPwrGetAcc1bitTpc */
1569 /***********************************************************
1571 * Func : rgSCHPwrGetAcc2bitTpc
1573 * Desc : Allocate PDCCH for group power control
1581 **********************************************************/
1583 PRIVATE Void rgSCHPwrGetAcc2bitTpc
1590 PRIVATE Void rgSCHPwrGetAcc2bitTpc(remPwr, tpc, delta)
1603 U8 tpcs[3] = {1, 2, 2};
1604 U8 deltas[3] = {0, 1, 1};
1605 TRC2(rgSCHPwrGetAcc2bitTpc);
1611 else if (remPwr >= 3)
1618 *tpc = tpcs[(U8)remPwr];
1619 *delta = deltas[(U8)remPwr];
1622 } /* rgSCHPwrGetAcc2bitTpc */
1624 /***********************************************************
1626 * Func : rgSCHPwrGetAbsTpc
1628 * Desc : Allocate PDCCH for group power control
1636 **********************************************************/
1638 PRIVATE Void rgSCHPwrGetAbsTpc
1645 PRIVATE Void rgSCHPwrGetAbsTpc(remPwr, tpc, delta)
1651 TRC2(rgSCHPwrGetAbsTpc);
1664 else if (remPwr < 1)
1669 else if (remPwr < 4)
1680 } /* rgSCHPwrGetAbsTpc */
1682 /***********************************************************
1684 * Func : rgSCHPwrOnPucchGrpPwrForUe
1686 * Desc : Processing on sending TPC for UE through group power
1687 * control. Apart from updating remPwr, this only takes
1688 * care of possibly removing UE from scheduled
1690 * It does not take care of possibly removing TPC RNTI
1691 * from scheduled list in cell. This is done
1692 * in the caller after TPC for all UEs has been
1693 * determined. (This is where it differs
1694 * from the usual OnSendingPu[cs]ch TPC]
1702 **********************************************************/
1704 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe
1711 PRIVATE Void rgSCHPwrOnPucchGrpPwrForUe(cell, ue, delta)
1717 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1722 TRC2(rgSCHPwrOnPucchGrpPwrForUe);
1724 uePwr->remPucchPwr -= delta;
1726 /* UE was already scheduled for PUCCH group power
1727 * control which is why we came here. Don't
1728 * again check for this. */
1730 /* UE was scheduled for pucch grp pwr, sent TPC may
1731 * possibly cause it to be removed. */
1732 if (!uePwr->remPucchPwr)
1738 rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
1739 /* Not removing TPC RNTI from scheduled list,
1740 * this will happen in the caller once this
1741 * function is called for every UE scheduled. */
1746 /***********************************************************
1748 * Func : rgSCHPwrOnPuschGrpPwrForUe
1750 * Desc : Processing on sending TPC for UE through group power
1751 * control. Apart from updating remPwr, this only takes
1752 * care of possibly removing UE from scheduled
1754 * It does not take care of possibly removing TPC RNTI
1755 * from scheduled list in cell. This is done
1756 * in the caller after TPC for all UEs has been
1757 * determined. (This is where it differs
1758 * from the usual OnSendingPu[cs]ch TPC]
1766 **********************************************************/
1768 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe
1775 PRIVATE Void rgSCHPwrOnPuschGrpPwrForUe(cell, ue, delta)
1781 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
1785 TRC2(rgSCHPwrOnPuschGrpPwrForUe);
1787 uePwr->delta = delta;
1788 uePwr->remPuschPwr -= delta;
1789 if (uePwr->isPhrAvail)
1791 uePwr->phVal -= uePwr->delta;
1792 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
1795 /* UE was already scheduled for PUSCH group power
1796 * control which is why we came here. Don't
1797 * again check for this. */
1799 /* UE was scheduled for pusch grp pwr, sent TPC may
1800 * possibly cause it to be removed. */
1802 if (!uePwr->remPuschPwr)
1809 rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
1810 /* Not removing TPC RNTI from scheduled list,
1811 * this will happen in the caller once this
1812 * function is called for every UE scheduled. */
1817 /***********************************************************
1819 * Func : rgSCHPwrIsDlUeSched
1821 * Desc : Check if UE is scheduled in the passed DL SF
1829 **********************************************************/
1831 PRIVATE Bool rgSCHPwrIsDlUeSched
1838 PRIVATE Bool rgSCHPwrIsDlUeSched(cell, ue, sf)
1844 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1845 RgSchDlHqProcCb *proc = rgSCHDhmLastSchedHqProc(hqEnt);
1847 TRC2(rgSCHPwrIsDlUeSched);
1855 * The following subframe check is assumed enough, since
1856 * scheduled procs stay for a short time (until feedback
1857 * arrives), which typically is expected to have a
1858 * turnaround time of less than 8 subframes. So
1859 * we are probably never going to come across cases
1860 * where a process stays in the list for more than
1861 * 10 subframes, which would have otherwise caused
1862 * the check to succeed for a possibly older process.
1864 if ((proc->tbInfo[0].timingInfo.slot == sf->sfNum) ||
1865 (proc->tbInfo[1].timingInfo.slot == sf->sfNum))
1868 * Later, if a proc can be scheduled without having an
1869 * associated PDCCH, need to also check if PDCCH exists.
1870 * This is because for power, what matters is whether
1871 * TPC is going out for UE at this time or not, at least
1872 * that is what this function was introduced for.
1873 * Checking for PDCCH would have to be in common proc
1874 * the way things are now.
1882 } /* rgSCHPwrIsDlUeSched */
1884 /***********************************************************
1886 * Func : rgSCHPwrIsUlUeSched
1888 * Desc : Check if UE is scheduled in the passed UL SF
1896 **********************************************************/
1898 PRIVATE Bool rgSCHPwrIsUlUeSched
1905 PRIVATE Bool rgSCHPwrIsUlUeSched(cell, ue, sf)
1911 RgSchCmnUlCell *cmnCell = RG_SCH_CMN_GET_UL_CELL(cell);
1912 RgSchUlHqProcCb *proc = rgSCHUhmGetUlHqProc(cell, ue, cmnCell->schdHqProcIdx);
1914 TRC2(rgSCHPwrIsUlUeSched);
1918 #if (ERRCLASS & ERRCLS_DEBUG)
1933 } /* rgSCHPwrIsUlUeSched */
1936 * @brief Handles Pucch power delta indication recieved from PHY
1940 * Function : rgSCHPwrPucchDeltaInd
1942 * Invoking Module Processing:
1943 * - This shall be invoked on reception of Pucch power
1944 * delta indication from PHY.
1947 * - Update the remPucchPwr
1948 * ue->remPucchPwr = pwrDelta
1949 * - If (ue->tpcPucchRntiCb)
1950 * - If (fmtType = 3A)
1951 * - if (remPucchPwr >= 2 || remPucchPwr <= -2 )
1952 * - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1953 * - Add tpcPucchRntiCb to the pucchGrpPwr list.
1954 * - If not added, add to toBeSchdLst
1956 * - If already added, remove from toBeSchdLst
1957 * - else If (fmtType == 3)
1958 * - if (remPucchPwr)
1959 * - if (tpcPucchRntiCb is not in the pucchGrpPwr List)
1960 * - Add tpcPucchRntiCb to the pucchGrpPwr list.
1961 * - If not added, add to toBeSchdLst
1963 * - If already added, remove from toBeSchdLst
1965 * @param[in] RgSchCellCb *cell
1966 * @param[in] RgSchUeCb *ue
1967 * @param[in] U8 pwrDelta
1971 PUBLIC Void rgSCHPwrPucchDeltaInd
1978 PUBLIC Void rgSCHPwrPucchDeltaInd(cell, ue, pwrDelta)
1984 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
1985 RgSchCmnTpcRntiCb *cb;
1987 TRC2(rgSCHPwrPucchDeltaInd);
1989 uePwr->remPucchPwr = pwrDelta;
1991 if ((cb = uePwr->tpcPucchRntiCb) == NULLP)
1998 if (0 != uePwr->remPucchPwr)
2006 rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue);
2010 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
2017 * @brief Does processing after TPC for Pucch has been sent
2021 * Function : rgSCHPwrOnSchedPucchTpc
2023 * Invoking Module Processing:
2024 * - It shall be invoked after it is determined that PDCCH for UE
2025 * is finalised to go out, and thus TPC for PUCCH is being
2029 * - Update remPucchPwr with the delta
2030 * - Do group power control related processing
2032 * @param[in] RgSchCellCb *cell
2033 * @param[in] RgSchUeCb *ue
2034 * @param[in] S8 delta
2038 PRIVATE Void rgSCHPwrOnSchedPucchTpc
2045 PRIVATE Void rgSCHPwrOnSchedPucchTpc(cell, ue, delta)
2051 /* Similar to rgSCHPwrPucchDeltaInd.. not reusing
2052 * that since we use the fact that UE could only have
2053 * improved its remPwr as part of power control. */
2054 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2056 TRC2(rgSCHPwrOnSchedPucchTpc);
2058 uePwr->remPucchPwr -= delta;
2060 if (uePwr->schdPucchGrpLnk.node == NULLP)
2065 /* UE was scheduled for TPC, sent TPC may
2066 * possibly cause it to be removed. */
2068 if (!uePwr->remPucchPwr)
2075 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2076 if (uePwr->tpcPucchRntiCb->toBeSchdUes.count == 0)
2078 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb);
2086 * @brief Does processing after TPC for Pusch has been sent
2090 * Function : rgSCHPwrOnSchedPuschTpc
2094 * - Update remPuschPwr with the delta
2095 * - Do group power related processing if applicable
2097 * @param[in] RgSchCellCb *cell
2098 * @param[in] RgSchUeCb *ue
2102 PRIVATE Void rgSCHPwrOnSchedPuschTpc
2108 PRIVATE Void rgSCHPwrOnSchedPuschTpc(cell, ue)
2113 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2115 TRC2(rgSCHPwrOnSchedPuschTpc);
2117 /* Don't do anything for the case of absolute TPC commands */
2118 if (!uePwr->isAccumulated)
2123 uePwr->remPuschPwr -= uePwr->delta;
2124 if (uePwr->isPhrAvail)
2126 uePwr->phVal -= uePwr->delta;
2127 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2130 if (uePwr->schdPuschGrpLnk.node == NULLP)
2135 /* UE was scheduled for pusch TPC, sent TPC may
2136 * possibly cause it to be removed. */
2138 if (!uePwr->remPuschPwr)
2145 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2152 * @brief Handles PHR updation for the UE
2156 * Function : rgSCHPwrUpdExtPhr
2157 * @param[in] RgSchCellCb *cell
2158 * @param[in] RgSchUeCb *ue
2159 * @param[in] RgInfExtPhrCEInfo *extPhr
2160 * @param[in] RgSchCmnAllocRecord allocInfo
2164 PUBLIC Void rgSCHPwrUpdExtPhr
2168 RgInfExtPhrCEInfo *extPhr,
2169 RgSchCmnAllocRecord *allocInfo
2172 PUBLIC Void rgSCHPwrUpdExtPhr(cell, ue, extPhr, allocInfo)
2175 RgInfExtPhrCEInfo *extPhr;
2176 RgSchCmnAllocRecord *allocInfo;
2180 RgInfExtPhrSCellInfo *servCellPhr;
2183 TRC2(rgSCHPwrUpdExtPhr);
2185 for (idx = 0; idx < extPhr->numServCells; idx++)
2187 servCellPhr = &extPhr->servCellPhr[idx];
2189 if (RG_SCH_REF_PCMAX == servCellPhr->pCmax)
2191 pCMax = RG_SCH_CMN_PWR_USE_CFG_MAX_PWR;
2195 pCMax = rgSCHPwrGetPCMaxValFromPCMax(servCellPhr->pCmax);
2197 rgSCHPwrUpdPhr(ue->cellInfo[servCellPhr->sCellIdx]->cell,
2198 ue, servCellPhr->phr, allocInfo, pCMax);
2204 * @brief Handles PHR updation for the UE
2208 * Function : rgSCHPwrUpdPhr
2210 * Invoking Module Processing:
2211 * - This shall be invoked on reception of PHR from MAC to SCH. It shall
2212 * pass the information of number of RBs, coding efficiency and TPC for
2213 * the Pusch transmission for which PHR has been reported.
2216 * - Compute power per RB using the PHR report
2217 * - ue_transmit_pwr = ue_max_pwr - PHR
2218 * - if isDeltaMcs = TRUE
2219 * - ue_transmit_pwr -
2220 * [10log(phr_num_rb) + 10log(2^ (1.25 * phr_coding_effeciency) -1)
2221 * + phr_tpc(if absolute TPC)] = pwrPerRB
2223 * - ue_transmit_pwr - [10log(phr_num_rb) + phr_tpc(if absolute TPC)]
2225 * (Use the number of RBs and efficiency used by UE which caused the PHR
2227 * - Adjust PHR according to last allocation (take into account
2228 * number of RBs granted in the last allocation)
2229 * - Update the PHR report in the control block
2230 * - Set isPhrAvail = TRUE
2231 * - Do group power control related processing if applicable
2233 * @param[in] RgSchCellCb *cell
2234 * @param[in] RgSchUeCb *ue
2236 * @param[in] RgSchCmnAllocRecord allocInfo
2237 * @param[in] U8 maxUePwr
2241 PUBLIC Void rgSCHPwrUpdPhr
2246 RgSchCmnAllocRecord *allocInfo,
2250 PUBLIC Void rgSCHPwrUpdPhr(cell, ue, phr, allocInfo, maxUePwr)
2254 RgSchCmnAllocRecord *allocInfo;
2258 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2261 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2263 TRC2(rgSCHPwrUpdPhr);
2265 uePwr->phVal = rgSCHPwrGetPhValFromPhr(phr);
2267 if (maxUePwr == RG_SCH_CMN_PWR_USE_CFG_MAX_PWR)
2269 maxUePwr = uePwr->maxUePwr;
2271 rbPwr = rgSCHPwrRbToPwr(cell,allocInfo->numRb);
2272 effPwr = rgSCHPwrGetCqiPwrForUe(cell, ue, allocInfo->cqi);
2273 uePwr->pwrPerRb = maxUePwr - uePwr->phVal - rbPwr - effPwr;
2274 /*if (!uePwr->isAccumulated)
2276 uePwr->pwrPerRb -= rgSCHPwrGetDeltaFrmAbsTpc(allocInfo->tpc);
2279 /* Let headroom reflect remaining power according to last
2280 * allocated number of RBs. Intermediate TPCs not yet
2281 * taken care of (for accumulated case, it is anyway
2282 * not applicable for absolute commands). */
2283 uePwr->phVal -= (rgSCHPwrRbToPwr(cell, cellUl->sbSize)) - rbPwr;
2284 uePwr->phVal = RGSCH_MAX(-23, uePwr->phVal);
2285 uePwr->isPhrAvail = TRUE;
2287 rgSCHPwrOnPuschPwrUpd(cell, ue);
2289 RLOG_ARG4(L_DEBUG,DBG_UEID,ue->ueId,
2290 "Output: Reported PHR[%d] cqi[%u] allocRb[%u] uePwr->pwrPerRb[%d]",
2299 * @brief Handles UL CQI indication
2303 * Function : rgSCHPwrUlCqiInd
2305 * Invoking Module Processing:
2306 * - This shall be invoked when uplink CQI indication
2307 * is receiving from PHY for a UE.
2310 * - Update remPuschPwr.
2311 * - Possibly schedule for group power control.
2313 * @param[in] RgSchCellCb *cell
2314 * @param[in] RgSchUeCb *ue
2315 * @param[in] U8 numRb
2319 PUBLIC Void rgSCHPwrUlCqiInd
2325 PUBLIC Void rgSCHPwrUlCqiInd(cell, ue)
2330 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2331 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2335 TRC2(rgSCHPwrUlCqiInd);
2338 * For absolute power cmd case, we could look at the time
2339 * at which CQI was received, determine if there was a
2340 * PUSCH TPC cmd for that time (this could come from
2341 * group power control too), and (if this
2342 * CQI report is indeed based on the the PUSCH tx)
2343 * then factor in that cmd here. Not doing
2347 /* See how much power needs to be adjusted based on cqi
2349 uePwr->remPuschPwr =
2351 rgSCHPwrGetDelta2FrmCqi(ueUl->validUlCqi, uePwr->trgCqi, ue, cell);
2353 rgSCHPwrGetDelta2FrmCqi(ueUl->crntUlCqi[0], uePwr->trgCqi, ue, cell);
2356 rgSCHPwrOnPuschPwrUpd(cell, ue);
2358 if(uePwr->maxPwrDeltaByPhr < 0)
2360 tmp = ueUl->validUlCqi;
2361 tmp = tmp + uePwr->maxPwrDeltaByPhr;
2364 ueUl->validUlCqi = 1;
2368 ueUl->validUlCqi = tmp;
2377 * @brief Updates the stored last number of RBs allocated
2381 * Function : rgSCHPwrRecordRbAlloc
2383 * Invoking Module Processing:
2384 * - This shall be invoked when uplink allocation is made for
2386 * - Note: If outstanding TPCs are considered at the time
2387 * of PHR report, the last numRb would also be known
2388 * and then this API would not be needed.
2391 * - Adjust PHR according to now allocated number of RBs
2392 * - Store the number of RBs
2394 * @param[in] RgSchCellCb *cell
2395 * @param[in] RgSchUeCb *ue
2396 * @param[in] U8 numRb
2400 PUBLIC Void rgSCHPwrRecordRbAlloc
2407 PUBLIC Void rgSCHPwrRecordRbAlloc(cell, ue, numRb)
2413 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2415 TRC2(rgSCHPwrRecordRbAlloc);
2418 if (uePwr->isPhrAvail)
2420 uePwr->phVal += rgSCHPwrRbToPwr(cell,numRb) - rgSCHPwrRbToPwr(cell,uePwr->numRb);
2421 uePwr->phVal = RGSCH_MIN(40, uePwr->phVal);
2423 uePwr->numRb = numRb;
2428 * @brief Handles power related configuration for a cell
2432 * Function : rgSCHPwrCellCfg
2434 * Invoking Module Processing:
2435 * - This shall be invoked during cell config
2440 * - Update TPC-RNTI information for the cell for Pucch and Pusch.
2441 * - For each TPC-Pucch-RNTI,
2442 * - Call rgSCHAddRntiToPucchRntiLst()
2443 * - For each TPC-Pusch-RNTI,
2444 * - Call rgSCHAddRntiToPuschRntiLst()
2447 * @param[in] RgSchCellCb *cell
2448 * @param[in] RgrCellCfg *cfg
2454 PUBLIC S16 rgSCHPwrCellCfg
2460 PUBLIC S16 rgSCHPwrCellCfg(cell, cfg)
2465 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2467 CmLteRnti startRnti;
2470 TRC2(rgSCHPwrCellCfg);
2472 /* Right now, all UEs have fixed maximum power capability. So
2473 * we store cell wide pMax as minimum of configured pMax and
2475 cellPwr->pMax = RGSCH_MIN(cfg->pMax, RG_SCH_PWR_UE_MAX_PWR);
2477 /* trgUlCqi already validated by common */
2478 cellPwr->trgUlCqi = cfg->trgUlCqi.trgCqi;
2480 /* Validate number of TPC RNTIs */
2481 if ((cfg->pwrCfg.pucchPwrFmt3.size + cfg->pwrCfg.pucchPwrFmt3a.size
2482 > RG_SCH_CMN_MAX_NUM_TPC_PUCCH_RNTI)
2483 || (cfg->pwrCfg.puschPwrFmt3.size + cfg->pwrCfg.puschPwrFmt3a.size
2484 > RG_SCH_CMN_MAX_NUM_TPC_PUSCH_RNTI))
2489 /* Now initialise TPC RNTIs */
2491 /* Format 3 Pucch TPC RNTIs */
2493 startRnti = cfg->pwrCfg.pucchPwrFmt3.startTpcRnti;
2494 size = cfg->pwrCfg.pucchPwrFmt3.size;
2495 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2497 rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2500 /* Format 3A Pucch TPC RNTIs */
2502 startRnti = cfg->pwrCfg.pucchPwrFmt3a.startTpcRnti;
2503 size = cfg->pwrCfg.pucchPwrFmt3a.size;
2504 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2506 rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a);
2509 /* Format 3 Pusch TPC RNTIs */
2511 startRnti = cfg->pwrCfg.puschPwrFmt3.startTpcRnti;
2512 size = cfg->pwrCfg.puschPwrFmt3.size;
2513 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2515 rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2518 /* Format 3A Pusch TPC RNTIs */
2520 startRnti = cfg->pwrCfg.puschPwrFmt3a.startTpcRnti;
2521 size = cfg->pwrCfg.puschPwrFmt3a.size;
2522 for (rnti = startRnti; (rnti < startRnti + size); ++rnti)
2524 rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a);
2531 * @brief Handles power related re-configuration for a cell
2535 * Function : rgSCHPwrCellRecfg
2540 * @param[in] RgSchCellCb *cell
2541 * @param[in] RgrCellRecfg *recfg
2546 PUBLIC S16 rgSCHPwrCellRecfg
2552 PUBLIC S16 rgSCHPwrCellRecfg(cell, recfg)
2554 RgrCellRecfg *recfg;
2559 TRC2(rgSCHPwrCellRecfg);
2561 /* Not doing anything for power reconfig, so such structure
2567 * @brief Frees power related data structures in cell
2571 * Function : rgSCHPwrCellDel
2576 * @param[in] RgSchCellCb *cell
2580 PUBLIC Void rgSCHPwrCellDel
2585 PUBLIC Void rgSCHPwrCellDel(cell)
2590 TRC2(rgSCHPwrCellDel);
2592 /* There is no allocated memory, so do nothing */
2599 * @brief Configures ULPC CB for a SCELL being added
2603 * Function : rgSCHPwrUeSCellCfg
2605 * @param[in] RgSchCellCb *cell
2606 * @param[in] RgSchUeCb *ue
2607 * @param[in] RgrUeCfg *cfg
2613 PUBLIC S16 rgSCHPwrUeSCellCfg
2617 RgrUeSecCellCfg *sCellInfoCfg
2620 PUBLIC S16 rgSCHPwrUeSCellCfg(cell, ue, sCellInfoCfg)
2623 RgrUeSecCellCfg *sCellInfoCfg;
2626 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2627 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2628 RgSchCmnUeUlPwrCb *uePwrPCell = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
2629 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2631 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2633 TRC2(rgSCHPwrUeSCellCfg);
2635 uePwr->maxUePwr = cellPwr->pMax;
2636 uePwr->trgCqi = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2639 uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2641 uePwr->isPhrAvail = FALSE;
2643 uePwr->maxUlRbs = RGSCH_MAX_DL_BW;
2645 uePwr->puschTpc = 1;
2646 uePwr->remPuschPwr = 0;
2648 /* Rest of the vars update and group power control related
2649 * config happens in the function below */
2650 uePwr->isAccumulated = sCellInfoCfg->ueSCellUlDedPwrCfg.isAccumulated;
2651 uePwr->deltaMcsEnbld = sCellInfoCfg->ueSCellUlDedPwrCfg.isDeltaMCSEnabled;
2653 uePwr->trgCqi = uePwrPCell->trgCqi;
2655 if (ueUl->maxUlCqi < uePwr->trgCqi)
2657 uePwr->trgCqi = ueUl->maxUlCqi;
2659 uePwr->p0UePusch = sCellInfoCfg->ueSCellUlDedPwrCfg.p0UePusch;
2666 * @brief Handles power related configuration for a UE
2670 * Function : rgSCHPwrUeCfg
2673 * - If Pusch group power configuration exists && accumulation enabled,
2674 * - Fetch the TPC-Pusch-RNTI control block for the configured
2675 * TPC-Pusch-RNTI. Call rgSCHGetRntiFrmPuschRntiLst(). If it does not
2676 * exist, return RFAILED.
2677 * - Add Ue to the ueLst of TPC-Pusch-RNTI control block.
2678 * - Update tpcPuschRntiCb pointer in UE.
2679 * - Update the puschIdx value.
2680 * - If Pucch group power configuration exists && accumulation enabled,
2681 * - Fetch the TPC-Pucch-RNTI control block for the configured
2682 * TPC-Pucch-RNTI. Call rgSCHGetRntiFrmPucchRntiLst(). If it does not
2683 * exist, return RFAILED.
2684 * - Add Ue to the ueLst of TPC-Pucch-RNTI control block.
2685 * - Update tpcPucchRntiCb pointer in UE.
2686 * - Update the pucchIdx value.
2687 * - Update isAccumulated and isDeltaMcs variables.
2688 * - maxUlRbs = configured maximum UL bandwidth value per UE.
2689 * - trgUlCqi = configured value, if any, else cell-wide default trg CQI value.
2690 * - If format type is format 3A, update remaining power to +1
2691 * - Update TPC-RNTI information for the cell for Pucch and Pusch.
2694 * @param[in] RgSchCellCb *cell
2695 * @param[in] RgSchUeCb *ue
2696 * @param[in] RgrUeCfg *cfg
2702 PUBLIC S16 rgSCHPwrUeCfg
2709 PUBLIC S16 rgSCHPwrUeCfg(cell, ue, cfg)
2716 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
2717 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2719 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
2721 TRC2(rgSCHPwrUeCfg);
2723 uePwr->maxUePwr = cellPwr->pMax;
2724 uePwr->trgCqi = cellPwr->trgUlCqi; /* Overriding with UE's happens later */
2727 uePwr->maxPwrPerRb = uePwr->maxUePwr - rgSchPwrRbToPwrTbl[cellUl->sbSize];
2729 rgSCHPwrUeResetPucch(cell, ue);
2730 rgSCHPwrUeResetPusch(cell, ue);
2732 /* Rest of the vars update and group power control related
2733 * config happens in the function below */
2734 ret = rgSCHPwrApplyUePwrCfg(cell, ue, &cfg->ueUlPwrCfg);
2740 * @brief Handles power related re-configuration for a UE
2744 * Function : rgSCHPwrUeRecfg
2746 * Invoking Module Processing:
2747 * - This shall be invoked by SCH_GOM at UE re-configuration.
2750 * - If change in TPC-RNTI, update the pointer and the TPC RNTI Cb appropriately.
2751 * - If accumulation disabled, remove the UE from TPC-RNTI lists of UE, if
2753 * - If group power configuration disabled, remove the UE from TPC-RNTI lists of UE, if
2756 * @param[in] RgSchCellCb *cell
2757 * @param[in] RgSchUeCb *ue
2758 * @param[in] RgrUeRecfg *recfg
2765 PUBLIC S16 rgSCHPwrUeRecfg
2772 PUBLIC S16 rgSCHPwrUeRecfg(cell, ue, recfg)
2779 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2780 RgrUeUlPwrCfg *pwrCfg = &recfg->ueUlPwrRecfg;
2781 TRC2(rgSCHPwrUeRecfg);
2783 if (pwrCfg->p0UePucch != uePwr->p0UePucch)
2785 rgSCHPwrUeResetPucch(cell, ue);
2787 if ((pwrCfg->isAccumulated != uePwr->isAccumulated)
2788 || (pwrCfg->p0UePusch != uePwr->p0UePusch))
2790 rgSCHPwrUeResetPusch(cell, ue);
2792 ret = rgSCHPwrApplyUePwrCfg(cell, ue, &recfg->ueUlPwrRecfg);
2797 /***********************************************************
2799 * Func : rgSCHPwrApplyUePwrCfg
2801 * Desc : Applies power config for UE. Meants to be
2802 * used during both power config and reconfig.
2810 **********************************************************/
2812 PRIVATE S16 rgSCHPwrApplyUePwrCfg
2816 RgrUeUlPwrCfg *pwrCfg
2819 PRIVATE S16 rgSCHPwrApplyUePwrCfg(cell, ue, pwrCfg)
2822 RgrUeUlPwrCfg *pwrCfg;
2826 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
2827 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2828 RgSchCmnTpcRntiCb *pucchRntiCb = NULLP;
2829 RgSchCmnTpcRntiCb *puschRntiCb = NULLP;
2832 TRC2(rgSCHPwrApplyUePwrCfg);
2834 /* Validate Pucch group power control config */
2835 if (pwrCfg->uePucchPwr.pres)
2838 rgSCHPwrGetPucchRntiCb(cell, pwrCfg->uePucchPwr.tpcRnti);
2839 if (pucchRntiCb == NULLP)
2843 pucchIdx = pwrCfg->uePucchPwr.idx;
2844 ret = rgSCHPwrChkPucchTpcRntiIdx(pucchRntiCb, pucchIdx);
2851 /* Validate Pusch group power control config */
2852 if (pwrCfg->uePuschPwr.pres)
2855 rgSCHPwrGetPuschRntiCb(cell, pwrCfg->uePuschPwr.tpcRnti);
2856 if (puschRntiCb == NULLP)
2860 puschIdx = pwrCfg->uePuschPwr.idx;
2861 ret = rgSCHPwrChkPuschTpcRntiIdx(puschRntiCb, puschIdx);
2868 /* Apply Pucch group power control config */
2871 if (uePwr->tpcPucchRntiCb != pucchRntiCb) /* This part for recfg */
2873 if (uePwr->tpcPucchRntiCb)
2875 rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2877 uePwr->tpcPucchRntiCb = pucchRntiCb;
2878 rgSCHPwrAddUeToPucchTpcRntiCb(cell, pucchRntiCb, ue);
2880 uePwr->pucchIdx = pucchIdx;
2882 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2883 "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2884 pucchRntiCb->cfgdUes.count,((U32)pucchRntiCb->cfgdUes.first),
2885 ((U32)pucchRntiCb->cfgdUes.last),ue->ueId);
2886 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2887 "UEID:%d isFmt3a(%u) ueNode(%ld)",
2888 ue->ueId,pucchRntiCb->isFmt3a,
2889 pucchRntiCb->schdLnk.node);
2890 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2891 "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)",
2892 pucchRntiCb->toBeSchdUes.count,
2893 ((U32)pucchRntiCb->toBeSchdUes.first),
2894 ((U32)pucchRntiCb->toBeSchdUes.last),
2895 pucchRntiCb->tpcRnti);
2897 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2898 "<GRP_PWR>PucchRntiCb cfgdUes(%ld %lu %lu) UEID:%d",
2899 pucchRntiCb->cfgdUes.count,((U64)pucchRntiCb->cfgdUes.first),
2900 ((U64)pucchRntiCb->cfgdUes.last),ue->ueId);
2901 RLOG_ARG3(L_UNUSED,DBG_CELLID,cell->cellId,
2902 "UEID:%d isFmt3a(%u) ueNode(%ld)",
2903 ue->ueId,pucchRntiCb->isFmt3a,
2904 pucchRntiCb->schdLnk.node);
2905 RLOG_ARG4(L_UNUSED,DBG_CELLID,cell->cellId,
2906 "toBeSchdUes(%ld %lu %lu) tpcRnti(%u)",
2907 pucchRntiCb->toBeSchdUes.count,
2908 ((U64)pucchRntiCb->toBeSchdUes.first),
2909 ((U64)pucchRntiCb->toBeSchdUes.last),
2910 pucchRntiCb->tpcRnti);
2915 /* Apply Pusch group power control config */
2918 if (uePwr->tpcPuschRntiCb != puschRntiCb) /* This part for recfg */
2920 if (uePwr->tpcPuschRntiCb)
2922 rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2924 uePwr->tpcPuschRntiCb = puschRntiCb;
2925 rgSCHPwrAddUeToPuschTpcRntiCb(puschRntiCb, ue);
2927 uePwr->puschIdx = puschIdx;
2931 uePwr->isAccumulated = pwrCfg->isAccumulated;
2932 uePwr->deltaMcsEnbld = pwrCfg->isDeltaMCSEnabled;
2935 uePwr->trgCqi = pwrCfg->trgCqi;
2937 if (ueUl->maxUlCqi < uePwr->trgCqi)
2939 uePwr->trgCqi = ueUl->maxUlCqi;
2941 uePwr->p0UePusch = pwrCfg->p0UePusch;
2942 uePwr->p0UePucch = pwrCfg->p0UePucch;
2949 * @brief Deletes power related information for UE
2953 * Function : rgSCHPwrUeDel
2955 * Invoking Module Processing:
2956 * - This shall be invoked by at the time of UE deletion.
2959 * - if (ue->tpcPucchRntiCb)
2960 * - delete UE from tpcPucchRntiCb->ueLst
2961 * - ue->tpcPucchRntiCb = NULLP
2962 * - If in (ue->tpcPucchRntiCb->toBeSchdLst)
2963 * - remove from the list.
2964 * - if (ue->tpcPuschRntiCb)
2965 * - delete UE from tpcPuschRntiCb->ueLst
2966 * - ue->tpcPuschRntiCb = NULLP
2967 * - If in (ue->tpcPuschRntiCb->toBeSchdLst)
2968 * - remove from the list.
2970 * @param[in] RgSchCellCb *cell
2971 * @param[in] RgSchUeCb *ue
2975 PUBLIC Void rgSCHPwrUeDel
2981 PUBLIC Void rgSCHPwrUeDel(cell, ue)
2986 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
2987 TRC2(rgSCHPwrUeDel);
2989 if (uePwr->tpcPucchRntiCb)
2991 rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
2992 uePwr->tpcPucchRntiCb = NULLP;
2994 if (uePwr->tpcPuschRntiCb)
2996 rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
2997 uePwr->tpcPuschRntiCb = NULLP;
3003 * @brief Resets UE's power state
3007 * Function : rgSCHPwrUeReset
3009 * Invoking Module Processing:
3010 * - This shall be invoked by at the time PDCCH order.
3013 * - Reset PUSCH power state
3014 * - Reset PUCCH power state
3016 * @param[in] RgSchCellCb *cell
3017 * @param[in] RgSchUeCb *ue
3021 PUBLIC Void rgSCHPwrUeReset
3027 PUBLIC Void rgSCHPwrUeReset(cell, ue)
3032 TRC2(rgSCHPwrUeReset);
3034 rgSCHPwrUeResetPucch(cell, ue);
3035 rgSCHPwrUeResetPusch(cell, ue);
3039 /***********************************************************
3041 * Func : rgSCHPwrUeResetPucch
3043 * Desc : This function is called to reset UE
3044 * to initial PUCCH power state.
3052 **********************************************************/
3054 PRIVATE Void rgSCHPwrUeResetPucch
3060 PRIVATE Void rgSCHPwrUeResetPucch(cell, ue)
3065 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3066 TRC2(rgSCHPwrUeResetPucch);
3068 uePwr->pucchTpc = 1;
3069 uePwr->remPucchPwr = 0;
3070 if (uePwr->tpcPucchRntiCb)
3072 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, uePwr->tpcPucchRntiCb, ue);
3075 /* Stack Crash problem for TRACE5 changes. Added the line below */
3080 /***********************************************************
3082 * Func : rgSCHPwrUeResetPusch
3084 * Desc : This function is called to reset UE
3085 * to initial PUSCH power state.
3093 **********************************************************/
3095 PRIVATE Void rgSCHPwrUeResetPusch
3101 PRIVATE Void rgSCHPwrUeResetPusch(cell, ue)
3106 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3107 TRC2(rgSCHPwrUeResetPusch);
3109 uePwr->isPhrAvail = FALSE;
3111 uePwr->maxUlRbs = RGSCH_MAX_DL_BW;
3113 uePwr->puschTpc = 1;
3114 uePwr->remPuschPwr = 0;
3115 if (uePwr->tpcPuschRntiCb)
3117 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, uePwr->tpcPuschRntiCb, ue);
3122 /***********************************************************
3124 * Func : rgSCHPwrOnPuschPwrUpd
3126 * Desc : This function is called whenever 'remPuschPwr'
3135 **********************************************************/
3137 PRIVATE Void rgSCHPwrOnPuschPwrUpd
3143 PRIVATE Void rgSCHPwrOnPuschPwrUpd(cell, ue)
3148 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, cell);
3149 RgSchCmnTpcRntiCb *cb;
3151 TRC2(rgSCHPwrOnPuschPwrUpd);
3153 if ((cb = uePwr->tpcPuschRntiCb) == NULLP)
3158 /* Not checking for uwPwr->isPhrAvail as uePwr->phVal
3159 * is set to a large value initially */
3163 if ((uePwr->phVal != 0) && (uePwr->remPuschPwr != 0))
3171 rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue);
3175 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3182 /***********************************************************
3184 * Func : rgSCHPwrAddRntiToPucchRntiLst
3187 * Desc : Adds RNTI to Pucch Rnti list and updates requisite
3192 * Notes: Assumed that array bounds are checked
3193 * in caller before adding.
3197 **********************************************************/
3199 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst
3206 PRIVATE Void rgSCHPwrAddRntiToPucchRntiLst(cell, rnti, isFmt3a)
3212 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3213 TRC2(rgSCHPwrAddRntiToPucchRntiLst);
3215 rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPucchRntiLst[cellPwr->tpcPucchRntiCnt++],
3220 /***********************************************************
3222 * Func : rgSCHPwrAddRntiToPuschRntiLst
3225 * Desc : Adds RNTI to Pusch Rnti list and updates requisite
3230 * Notes: Assumed that array bounds are checked
3231 * in caller before adding.
3235 **********************************************************/
3237 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst
3244 PRIVATE Void rgSCHPwrAddRntiToPuschRntiLst(cell, rnti, isFmt3a)
3250 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3251 TRC2(rgSCHPwrAddRntiToPuschRntiLst);
3253 rgSCHPwrInitTpcRntiCb(&cellPwr->tpcPuschRntiLst[cellPwr->tpcPuschRntiCnt++],
3258 /***********************************************************
3260 * Func : rgSCHPwrInitTpcRntiCb
3263 * Desc : Initialises a TPC RNTI CB
3271 **********************************************************/
3273 PRIVATE Void rgSCHPwrInitTpcRntiCb
3275 RgSchCmnTpcRntiCb *cb,
3280 PRIVATE Void rgSCHPwrInitTpcRntiCb(cb, rnti, isFmt3a)
3281 RgSchCmnTpcRntiCb *cb;
3286 TRC2(rgSCHPwrInitTpcRntiCb);
3288 cmMemset((U8 *)cb, 0, sizeof(*cb));
3290 cb->isFmt3a = isFmt3a;
3291 /* Not initialising lists as memset 0 takes care of it */
3292 /* cb->schdLnk.node is set when this rnti is to be scheduled */
3296 /***********************************************************
3298 * Func : rgSCHPwrGetPucchRntiCb
3301 * Desc : Gets TPC RNTI control block from Pucch rnti list
3303 * Ret : RgSchCmnTpcRntiCb * - Success
3310 **********************************************************/
3312 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb
3318 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPucchRntiCb(cell, tpcRnti)
3323 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3325 TRC2(rgSCHPwrGetPucchRntiCb);
3327 if (!cellPwr->tpcPucchRntiCnt)
3331 for (idx = 0; idx < cellPwr->tpcPucchRntiCnt; ++idx)
3333 if (cellPwr->tpcPucchRntiLst[idx].tpcRnti == tpcRnti)
3335 return (&cellPwr->tpcPucchRntiLst[idx]);
3341 /***********************************************************
3343 * Func : rgSCHPwrGetPuschRntiCb
3346 * Desc : Gets TPC RNTI control block from Pusch rnti list
3348 * Ret : RgSchCmnTpcRntiCb * - Success
3355 **********************************************************/
3357 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb
3363 PRIVATE RgSchCmnTpcRntiCb* rgSCHPwrGetPuschRntiCb(cell, tpcRnti)
3368 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3370 TRC2(rgSCHPwrGetPuschRntiCb);
3372 if (!cellPwr->tpcPuschRntiCnt)
3376 for (idx = 0; idx < cellPwr->tpcPuschRntiCnt; ++idx)
3378 if (cellPwr->tpcPuschRntiLst[idx].tpcRnti == tpcRnti)
3380 return (&cellPwr->tpcPuschRntiLst[idx]);
3387 /***********************************************************
3389 * Func : rgSCHPwrAddUeToPucchTpcRntiCb
3392 * Desc : Add UE to cfgd list of UEs in rnti cb
3400 **********************************************************/
3402 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb
3405 RgSchCmnTpcRntiCb *cb,
3409 PRIVATE Void rgSCHPwrAddUeToPucchTpcRntiCb(cell, cb, ue)
3411 RgSchCmnTpcRntiCb *cb;
3415 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3417 TRC2(rgSCHPwrAddUeToPucchTpcRntiCb);
3419 cmLListAdd2Tail(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3420 uePwr->pucchGrpLnk.node = (PTR)ue;
3424 /***********************************************************
3426 * Func : rgSCHPwrDelUeFrmPucchTpcRntiCb
3429 * Desc : Remove UE from Pucch TPC RNTI CB
3437 **********************************************************/
3439 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb
3442 RgSchCmnTpcRntiCb *cb,
3446 PRIVATE Void rgSCHPwrDelUeFrmPucchTpcRntiCb(cell, cb, ue)
3448 RgSchCmnTpcRntiCb *cb;
3452 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3453 TRC2(rgSCHPwrDelUeFrmPucchTpcRntiCb);
3455 rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue);
3456 cmLListDelFrm(&cb->cfgdUes, &uePwr->pucchGrpLnk);
3457 uePwr->pucchGrpLnk.node = NULLP;
3461 /***********************************************************
3463 * Func : rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3466 * Desc : Remove UE from to-be-scheduled list of UEs
3475 **********************************************************/
3477 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb
3480 RgSchCmnTpcRntiCb *cb,
3484 PRIVATE Void rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb(cell, cb, ue)
3486 RgSchCmnTpcRntiCb *cb;
3490 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3491 TRC2(rgSCHPwrRmvSchdUeFrmPucchTpcRntiCb);
3493 if (uePwr->schdPucchGrpLnk.node == NULLP)
3497 rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue);
3498 if (!cb->toBeSchdUes.count)
3500 rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb);
3505 /***********************************************************
3507 * Func : rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3509 * Desc : Remove UE from to-be-scheduled list of UEs
3510 * in Pucch RNTI CB. Do not both about
3511 * possibly removing Pucch RNTI CB from
3512 * the cell wide to-be-scheduled list.
3520 **********************************************************/
3522 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb
3525 RgSchCmnTpcRntiCb *cb,
3529 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb(cell, cb, ue)
3531 RgSchCmnTpcRntiCb *cb;
3535 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3536 TRC2(rgSCHPwrRmvSchdUeOnlyFrmPucchTpcRntiCb);
3538 if (uePwr->schdPucchGrpLnk.node != NULLP)
3540 cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3541 uePwr->schdPucchGrpLnk.node = NULLP;
3546 /***********************************************************
3548 * Func : rgSCHPwrRmvSchdPucchTpcRntiCb
3550 * Desc : Remove Pucch TPC RNTI CB from to-be-scheduled
3559 **********************************************************/
3561 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb
3564 RgSchCmnTpcRntiCb *cb
3567 PRIVATE Void rgSCHPwrRmvSchdPucchTpcRntiCb(cell, cb)
3569 RgSchCmnTpcRntiCb *cb;
3572 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3573 TRC2(rgSCHPwrRmvSchdPucchTpcRntiCb);
3575 if (cb->schdLnk.node == NULLP)
3579 cmLListDelFrm(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3580 cb->schdLnk.node = NULLP;
3584 /***********************************************************
3586 * Func : rgSCHPwrAddSchdUeToPucchTpcRntiCb
3588 * Desc : Add UE to to-be-scheduled list of UEs
3597 **********************************************************/
3599 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb
3602 RgSchCmnTpcRntiCb *cb,
3606 PRIVATE Void rgSCHPwrAddSchdUeToPucchTpcRntiCb(cell, cb, ue)
3608 RgSchCmnTpcRntiCb *cb;
3612 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3613 TRC2(rgSCHPwrAddSchdUeToPucchTpcRntiCb);
3615 if (uePwr->schdPucchGrpLnk.node != NULLP)
3617 /* UE is already in the list */
3620 cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPucchGrpLnk);
3621 uePwr->schdPucchGrpLnk.node = (PTR)ue;
3622 if (cb->toBeSchdUes.count == 1)
3624 /* This is first UE, so queue up this TPC RNTI
3626 rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb);
3631 /***********************************************************
3633 * Func : rgSCHPwrAddSchdPucchTpcRntiCb
3635 * Desc : Add Pucch TPC RNTI CB from to-be-scheduled
3644 **********************************************************/
3646 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb
3649 RgSchCmnTpcRntiCb *cb
3652 PRIVATE Void rgSCHPwrAddSchdPucchTpcRntiCb(cell, cb)
3654 RgSchCmnTpcRntiCb *cb;
3657 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3658 TRC2(rgSCHPwrAddSchdPucchTpcRntiCb);
3660 cmLListAdd2Tail(&cellPwr->pucchGrpPwr, &cb->schdLnk);
3661 cb->schdLnk.node = (PTR)cb;
3666 /***********************************************************
3668 * Func : rgSCHPwrAddUeToPuschTpcRntiCb
3671 * Desc : Add UE to cfgd list of UEs in rnti cb
3679 **********************************************************/
3681 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb
3683 RgSchCmnTpcRntiCb *cb,
3687 PRIVATE Void rgSCHPwrAddUeToPuschTpcRntiCb(cb, ue)
3688 RgSchCmnTpcRntiCb *cb;
3692 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3693 TRC2(rgSCHPwrAddUeToPuschTpcRntiCb);
3695 cmLListAdd2Tail(&cb->cfgdUes, &uePwr->puschGrpLnk);
3696 uePwr->puschGrpLnk.node = (PTR)ue;
3700 /***********************************************************
3702 * Func : rgSCHPwrAddSchdUeToPuschTpcRntiCb
3704 * Desc : Add UE to to-be-scheduled list of UEs
3713 **********************************************************/
3715 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb
3718 RgSchCmnTpcRntiCb *cb,
3722 PRIVATE Void rgSCHPwrAddSchdUeToPuschTpcRntiCb(cell, cb, ue)
3724 RgSchCmnTpcRntiCb *cb;
3728 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3729 TRC2(rgSCHPwrAddSchdUeToPuschTpcRntiCb);
3731 if (uePwr->schdPuschGrpLnk.node != NULLP)
3733 /* UE is already in the list */
3736 cmLListAdd2Tail(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3737 uePwr->schdPuschGrpLnk.node = (PTR)ue;
3738 if (cb->toBeSchdUes.count == 1)
3740 /* This is first UE, so queue up this TPC RNTI
3742 rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb);
3747 /***********************************************************
3749 * Func : rgSCHPwrDelUeFrmPuschTpcRntiCb
3752 * Desc : Add UE to cfgd list of UEs in rnti cb
3760 **********************************************************/
3762 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb
3765 RgSchCmnTpcRntiCb *cb,
3769 PRIVATE Void rgSCHPwrDelUeFrmPuschTpcRntiCb(cell, cb, ue)
3771 RgSchCmnTpcRntiCb *cb;
3775 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3776 TRC2(rgSCHPwrDelUeFrmPuschTpcRntiCb);
3778 rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue);
3779 cmLListDelFrm(&cb->cfgdUes, &uePwr->puschGrpLnk);
3780 uePwr->puschGrpLnk.node = NULLP;
3784 /***********************************************************
3786 * Func : rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3788 * Desc : Remove UE from to-be-scheduled list of UEs
3797 **********************************************************/
3799 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb
3802 RgSchCmnTpcRntiCb *cb,
3806 PRIVATE Void rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb(cell, cb, ue)
3808 RgSchCmnTpcRntiCb *cb;
3812 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3813 TRC2(rgSCHPwrRmvSchdUeFrmPuschTpcRntiCb);
3815 if (uePwr->schdPuschGrpLnk.node == NULLP)
3819 rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue);
3820 if (!cb->toBeSchdUes.count)
3822 rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb);
3827 /***********************************************************
3829 * Func : rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3831 * Desc : Remove UE from to-be-scheduled list of UEs
3832 * in Pusch RNTI CB. Do not both about
3833 * possibly removing Pusch RNTI CB from
3834 * the cell wide to-be-scheduled list.
3842 **********************************************************/
3844 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb
3847 RgSchCmnTpcRntiCb *cb,
3851 PRIVATE Void rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb(cell, cb, ue)
3853 RgSchCmnTpcRntiCb *cb;
3857 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
3858 TRC2(rgSCHPwrRmvSchdUeOnlyFrmPuschTpcRntiCb);
3860 if (uePwr->schdPuschGrpLnk.node != NULLP)
3862 cmLListDelFrm(&cb->toBeSchdUes, &uePwr->schdPuschGrpLnk);
3863 uePwr->schdPuschGrpLnk.node = NULLP;
3868 /***********************************************************
3870 * Func : rgSCHPwrAddSchdPuschTpcRntiCb
3872 * Desc : Add Pusch TPC RNTI CB from to-be-scheduled
3881 **********************************************************/
3883 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb
3886 RgSchCmnTpcRntiCb *cb
3889 PRIVATE Void rgSCHPwrAddSchdPuschTpcRntiCb(cell, cb)
3891 RgSchCmnTpcRntiCb *cb;
3894 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3895 TRC2(rgSCHPwrAddSchdPuschTpcRntiCb);
3897 cmLListAdd2Tail(&cellPwr->puschGrpPwr, &cb->schdLnk);
3898 cb->schdLnk.node = (PTR)cb;
3902 /***********************************************************
3904 * Func : rgSCHPwrRmvSchdPuschTpcRntiCb
3906 * Desc : Remove Pusch TPC RNTI CB from to-be-scheduled
3915 **********************************************************/
3917 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb
3920 RgSchCmnTpcRntiCb *cb
3923 PRIVATE Void rgSCHPwrRmvSchdPuschTpcRntiCb(cell, cb)
3925 RgSchCmnTpcRntiCb *cb;
3928 RgSchCmnUlPwrCb *cellPwr = RG_SCH_PWR_GETCELLPWR(cell);
3929 TRC2(rgSCHPwrRmvSchdPuschTpcRntiCb);
3931 if (cb->schdLnk.node == NULLP)
3935 cmLListDelFrm(&cellPwr->puschGrpPwr, &cb->schdLnk);
3936 cb->schdLnk.node = NULLP;
3940 /***********************************************************
3942 * Func : rgSCHPwrChkPucchTpcRntiIdx
3944 * Desc : Validate that the given index is OK to
3945 * be assigned to a new UE for the Pucch TPC
3954 **********************************************************/
3956 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx
3958 RgSchCmnTpcRntiCb *cb,
3962 PRIVATE S16 rgSCHPwrChkPucchTpcRntiIdx(cb, idx)
3963 RgSchCmnTpcRntiCb *cb;
3967 TRC2(rgSCHPwrChkPucchTpcRntiIdx);
3969 if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
3973 if (rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx) != ROK)
3980 /***********************************************************
3982 * Func : rgSCHPwrChkPuschTpcRntiIdx
3984 * Desc : Validate that the given index is OK to
3985 * be assigned to a new UE for the Pusch TPC
3994 **********************************************************/
3996 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx
3998 RgSchCmnTpcRntiCb *cb,
4002 PRIVATE S16 rgSCHPwrChkPuschTpcRntiIdx(cb, idx)
4003 RgSchCmnTpcRntiCb *cb;
4007 TRC2(rgSCHPwrChkPuschTpcRntiIdx);
4009 if (rgSCHPwrChkTpcRntiIdx(cb, idx) != ROK)
4013 if (rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx) != ROK)
4020 /***********************************************************
4022 * Func : rgSCHPwrChkUniqPucchTpcRntiIdx
4024 * Desc : Validate index against format type of TPC RNTI
4032 **********************************************************/
4034 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx
4036 RgSchCmnTpcRntiCb *cb,
4040 PRIVATE S16 rgSCHPwrChkUniqPucchTpcRntiIdx(cb, idx)
4041 RgSchCmnTpcRntiCb *cb;
4046 TRC2(rgSCHPwrChkUniqPucchTpcRntiIdx);
4048 for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
4050 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
4051 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
4052 if (uePwr->pucchIdx == idx)
4060 /***********************************************************
4062 * Func : rgSCHPwrChkUniqPuschTpcRntiIdx
4064 * Desc : Validate index against format type of TPC RNTI
4072 **********************************************************/
4074 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx
4076 RgSchCmnTpcRntiCb *cb,
4080 PRIVATE S16 rgSCHPwrChkUniqPuschTpcRntiIdx(cb, idx)
4081 RgSchCmnTpcRntiCb *cb;
4086 TRC2(rgSCHPwrChkUniqPuschTpcRntiIdx);
4088 for (lnk = cb->cfgdUes.first; lnk; lnk = lnk->next)
4090 RgSchUeCb *ue = (RgSchUeCb *)lnk->node;
4091 RgSchCmnUeUlPwrCb *uePwr = RG_SCH_PWR_GETUEPWR(ue, ue->cell);
4092 if (uePwr->puschIdx == idx)
4100 /***********************************************************
4102 * Func : rgSCHPwrChkTpcRntiIdx
4104 * Desc : Validate index against format type of TPC RNTI.
4112 **********************************************************/
4114 PRIVATE S16 rgSCHPwrChkTpcRntiIdx
4116 RgSchCmnTpcRntiCb *cb,
4120 PRIVATE S16 rgSCHPwrChkTpcRntiIdx(cb, idx)
4121 RgSchCmnTpcRntiCb *cb;
4125 TRC2(rgSCHPwrChkTpcRntiIdx);
4129 if (idx >= TFU_MAX_1BIT_TPC)
4136 if (idx >= TFU_MAX_2BIT_TPC)
4143 /* Warning Fix: Commenting out as not used */
4145 /***********************************************************
4147 * Func : rgSCHPwrGetPCMaxValFromPCMax
4149 * Desc : Returns the power headroom in dB
4150 * corresponding to a power headroom
4159 **********************************************************/
4161 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax
4166 PRIVATE S8 rgSCHPwrGetPCMaxValFromPCMax(pCMax)
4170 TRC2(rgSCHPwrGetPCMaxValFromPCMax);
4171 return ((pCMax & 63) - 30);
4176 /***********************************************************
4178 * Func : rgSCHPwrGetPhValFromPhr
4180 * Desc : Returns the power headroom in dB
4181 * corresponding to a power headroom
4190 **********************************************************/
4192 PRIVATE S8 rgSCHPwrGetPhValFromPhr
4197 PRIVATE S8 rgSCHPwrGetPhValFromPhr(phr)
4201 TRC2(rgSCHPwrGetPhValFromPhr);
4202 return ((phr & 63) - 23);
4207 /**********************************************************************
4210 **********************************************************************/