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 Entry point fucntions
29 **********************************************************************/
31 /** @file rg_sch_ram.c
32 @brief This file has APIs to handle the random access procedure functionality for the scheduler.
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_MODULE_ID=4096;
37 static int RLOG_FILE_ID=171;
39 /* header include files (.h) */
40 #include "envopt.h" /* environment options */
41 #include "envdep.h" /* environment dependent */
42 #include "envind.h" /* environment independent */
44 #include "gen.h" /* general */
45 #include "ssi.h" /* system services */
47 #include "cm_tkns.h" /* Common Token Defines */
48 #include "cm_llist.h" /* Common Link List Defines */
49 #include "cm_hash.h" /* Common Hash List Defines */
50 #include "cm_mblk.h" /* common memory link list library */
51 #include "cm_lte.h" /* Common LTE */
53 #include "rg_env.h" /* MAC Environment Defines */
54 #include "rgr.h" /* RGR Interface defines */
55 #include "rgm.h" /* RGR Interface defines */
56 #include "tfu.h" /* TFU Interface defines */
57 #include "lrg.h" /* LRG Interface defines */
58 #include "rg_env.h" /* Scheduler error defines */
59 #include "rg_sch_inf.h" /* Scheduler defines */
60 #include "rg_sch_err.h" /* Scheduler error defines */
61 #include "rg_sch.h" /* Scheduler defines */
62 #include "rg_sch_cmn.h"
63 #include "rl_interface.h"
64 #include "rl_common.h"
66 /* header/extern include files (.x) */
67 #include "gen.x" /* general */
68 #include "ssi.x" /* system services */
69 #include "cm5.x" /* Timer */
70 #include "cm_tkns.x" /* Common Token Definitions */
71 #include "cm_llist.x" /* Common Link List Definitions */
72 #include "cm_lib.x" /* Common Library Definitions */
73 #include "cm_hash.x" /* Common Hash List Definitions */
74 #include "cm_mblk.x" /* common memory link list library */
75 #include "cm_lte.x" /* Common LTE */
77 #include "rgr.x" /* RGR Interface includes */
78 #include "rgm.x" /* RGR Interface includes */
79 #include "tfu.x" /* TFU Interface includes */
80 #include "lrg.x" /* LRG Interface includes */
82 #include "rg_sch_inf.x" /* typedefs for Scheduler */
83 #include "rg_sch.x" /* Scheduler includes */
84 #include "rg_sch_cmn.x"
86 EXTERN Bool rgSCHRamVldtRgrEmtcUeCfg ARGS((
91 EXTERN S16 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst
95 EXTERN Void rgSCHEmtcUtlUpdCmnNb
99 EXTERN Void rgSCHEmtcHqPAlloc
107 PRIVATE Void rgSCHRamUlFreeAllocation ARGS((RgSchUlSf *sf,RgSchUlAlloc *alloc,
108 RgSchCellCb *cell,Bool isEmtc));
110 PRIVATE S16 rgSCHRamContResCrnti ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
111 RgSchRaCb *raCb, RgSchErrInfo *err));
112 PRIVATE S16 rgSCHRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
115 EXTERN S16 rgSCHEmtcRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
116 EXTERN S16 rgSCHRamEmtcContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
117 EXTERN Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
118 EXTERN Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
119 EXTERN Void rgSCHEmtcRaInfoFree ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
122 PRIVATE Void rgSCHChkContResGrdTmrExp ARGS((RgSchCellCb *cell));
123 PRIVATE Void rgSCHChkContResTmrExp ARGS((RgSchCellCb *cell));
124 PRIVATE Void rgSCHRamProcContResExp ARGS((RgSchCellCb *cell,
126 PRIVATE Void rgSCHRamProcContResGrdExp ARGS((RgSchCellCb *cell,
129 EXTERN Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
130 EXTERN Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
133 /* forward references */
136 * @brief Check configured preamble id not colliding with non dedicated or PDCCH
137 * order preamble sets. When valid preamble id given check that C-RNTI given
138 * in configuration is not amongst the C-RNTI'smanaged by scheduler
142 * Function : rgSCHRamVldtUeCfg
144 * Processing Steps: Check configured preamble id not colliding with non dedicated or PDCCH
145 * order preamble sets. When valid preamble id given check that C-RNTI given
146 * in configuration is not amongst the C-RNTI'smanaged by scheduler
148 * @param[in] RgSchCellCb *cell
149 * @param[in] RgrUeCfg *ueCfg
155 PUBLIC S16 rgSCHRamVldtUeCfg
161 PUBLIC S16 rgSCHRamVldtUeCfg(cell, ueCfg)
166 TRC2(rgSCHRamVldtUeCfg);
167 if (ueCfg->dedPreambleId.pres == PRSNT_NODEF)
169 if ((ueCfg->dedPreambleId.val < cell->rachCfg.numRaPreamble) ||
170 (ueCfg->dedPreambleId.val >= RGSCH_MAX_NUM_RA_PREAMBLE) ||
171 ((ueCfg->dedPreambleId.val >= cell->macPreambleSet.start) &&
172 (ueCfg->dedPreambleId.val <= cell->macPreambleSet.start +
173 cell->macPreambleSet.size - 1)) ||
174 ((ueCfg->crnti >= cell->rntiDb.rntiStart) &&
175 (ueCfg->crnti < cell->rntiDb.rntiStart + cell->rntiDb.maxRntis-1))
177 || (rgSCHRamVldtRgrEmtcUeCfg(cell,ueCfg))
188 * @brief Handler for Random Access Request
192 * Function : rgSCHRamProcRaReq
194 * -# Create a node for each TfuRaReqInfo element received
195 * -# Initialize the list with the above elements at the raRnti index
199 * @param[in] RgSchCellCb *cell
200 * @param[in] CmLteRnti raRnti
201 * @param[in] RgTfuRaReqInd *raReqInd
202 * @param[out] RgSchErrInfo *err
208 PUBLIC S16 rgSCHRamProcRaReq
213 TfuRachInfo *raReqInd,
214 CmLteTimingInfo timingInfo,
219 PUBLIC S16 rgSCHRamProcRaReq(raReqCnt, cell, raRnti, raReqInd, timingInfo, ue, err)
223 TfuRachInfo *raReqInd;
224 CmLteTimingInfo timingInfo;
229 RgSchRaReqInfo *raReqInfo;
236 TRC2(rgSCHRamProcRaReq)
239 /* SR_RACH_STATS : RACH REQ */
240 rgNumPrachRecvd += raReqInd->numRaReqInfo;
242 /* ccpu00132523- Moved out this from for loop as updating of raIndex is
243 * relates to only raRnti and all preambles having same raRnti*/
245 /* UL subframes do not occupy all the subframes in a radio frame.
246 * So RA Rnti index to be calculated based on actual UL subframe index. */
247 /* Get the actual subframe number */
248 tid = (raRnti-1)%RGSCH_NUM_SUB_FRAMES;
249 /* Get the frequency index in the subframe */
250 fid = ((raRnti-1) / RGSCH_NUM_SUB_FRAMES)* RGSCH_NUM_SUB_FRAMES;
251 /* Get the index of RA RNTI in the array */
252 raIndex = ((timingInfo.sfn % cell->raInfo.maxRaSize) \
253 * RGSCH_MAX_RA_RNTI_PER_SUBFRM * RGSCH_NUM_SUB_FRAMES) + \
255 /* Fixes for RACH handling in TDD: Removed deletion of queued RaReq */
257 /* ccpu00132523- Placing the raReq into array based on RA SFN */
258 raIndex = (timingInfo.sfn & 1) * RGSCH_MAX_RA_RNTI + raRnti-1;
261 /* allocate new raReqInfos and enqueue them */
262 if (raReqInd->raReqInfoArr[raReqCnt].rapId >= RGSCH_MAX_NUM_RA_PREAMBLE)
264 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
265 "RARNTI:%d rgSCHTomRaReqInd(): RAM processing failed errType(%d) ",
270 /* SR_RACH_STATS : DED PREAMB*/
271 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
278 if (raReqInd->raReqInfoArr[raReqCnt].rapId < cell->rachCfg.sizeRaPreambleGrpA)
280 cell->raPrmbs.preamGrpA++;
282 else if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
284 cell->raPrmbs.dedPream++;
288 cell->raPrmbs.preamGrpB++;
292 if((rgSCHUtlAllocSBuf(cell->instIdx, (Data **)(&raReqInfo),
293 sizeof(RgSchRaReqInfo))) == RFAILED)
295 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHRamProcRaReq(): Allocation"
296 " of RaReq failed RARNTI:%d",raRnti);
297 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
301 /* Insert the given raReqInfo */
303 raReqInfo->timingInfo = timingInfo;
304 raReqInfo->raReq = raReqInd->raReqInfoArr[raReqCnt];
305 raReqInfo->raReqLstEnt.next = NULLP;
306 raReqInfo->raReqLstEnt.prev = NULLP;
307 raReqInfo->raReqLstEnt.node = (PTR)raReqInfo;
312 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->raInfo.raReqLst, raIndex);
314 /* RACHO: If dedicated preamble, then give preference by appending at front */
315 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
317 cmLListFirst(&cell->raInfo.raReqLst[raIndex]);
318 cmLListInsCrnt(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
322 cmLListAdd2Tail(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
326 } /* rgSCHRamProcRaReq */
329 * @brief Handler for Random Access control block creation
333 * Function : rgSCHRamCreateRaCb
334 * Creates a raCb and gives the same to scheduler for its updation
337 * @param[in] RgSchCellCb *cell
338 * @param[in, out] RgSchRaCb **raCb
339 * @param[out] RgSchErrInfo *err
345 PUBLIC S16 rgSCHRamCreateRaCb
352 PUBLIC S16 rgSCHRamCreateRaCb(cell, raCb, err)
358 RgSchRntiLnk *rntiLnk;
359 Inst inst = cell->instIdx;
361 TRC2(rgSCHRamCreateRaCb)
363 if((rgSCHUtlAllocSBuf(inst, (Data **)(raCb),
364 sizeof(RgSchRaCb))) == RFAILED)
366 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHRamCreateRaCb(): Allocation of "
368 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
372 rntiLnk = rgSCHDbmGetRnti(cell);
375 (*raCb)->rntiLnk = rntiLnk;
376 (*raCb)->tmpCrnti = rntiLnk->rnti;
381 /* SR_RACH_STATS: RNTI POOL Exhaution */
382 rgNumRarFailDuetoRntiExhaustion++;
384 /* No rnti available! */
385 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHRamCreateRaCb(): Allocation of "
386 "temporary RNTI failed at MAC(CRNTI exhausted)");
387 /* ccpu00117052 - MOD - Passing double pointer
388 for proper NULLP assignment*/
389 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
390 err->errCause = RGSCHERR_RAM_RNTI_EXHAUST;
394 /* Allocate and initialize the DL HARQ portion of the RACB */
395 (*raCb)->dlHqE = rgSCHDhmHqEntInit(cell);
396 if ((*raCb)->dlHqE == NULLP)
398 /* No memory available! */
399 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"rgSCHRamCreateRaCb(): Creation of"
401 /* ccpu00117052 - MOD - Passing double pointer
402 for proper NULLP assignment*/
403 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
404 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
408 (*raCb)->isEmtcRaCb = FALSE;
409 rgSCHEmtcHqPAlloc(cell, (*raCb)->dlHqE);
411 (*raCb)->dlHqE->raCb = (*raCb);
412 /* Initialize RaCb's contents */
413 (*raCb)->timingInfo = cell->crntTime;
414 (*raCb)->raState = RGSCH_RA_MSG3_PENDING;
415 (*raCb)->toDel = FALSE;
416 (*raCb)->phr.pres = FALSE;
418 /* Insert the created raCb into raCb list of cell */
419 (*raCb)->raCbLnk.node = (PTR)(*raCb);
420 cmLListAdd2Tail(&cell->raInfo.raCbLst, &(*raCb)->raCbLnk);
423 } /* rgSCHRamCreateRaCb */
426 * @brief Handler for Ue Configuration Request
430 * Function : rgSCHRamRgrUeCfg
432 * This function handles the UE config received based on the state of the
434 * -# If raCb is in RGSCH_RA_MSG4_PENDING state, it shall update the harq
435 * information to UeCb and update the references.
436 * -# If raCb is in RGSCH_RA_MSG4_DONE, then it shall free the raCb
439 * @param[in] RgSchCellCb *cell
440 * @param[in,out] RgSchUeCb *ue
441 * @param[in,out] RgSchRaCb *raCb
442 * @param[out] RgSchErrInfo *err
448 PUBLIC S16 rgSCHRamRgrUeCfg
456 PUBLIC S16 rgSCHRamRgrUeCfg(cell, ue, raCb, err)
463 /* Releasing HARQ processes of old UE when ue
464 * reconfig with new crnti */
466 RgSchDlHqEnt **hqEnt = &(RG_SCH_CMN_GET_UE_HQE(ue, cell));
467 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
468 TRC2(rgSCHRamRgrUeCfg)
471 /* Fix : set UE inactive in DL until UE is reinitialization completed */
472 ue->dl.dlInactvMask |= RG_HQENT_INACTIVE;
473 ue->ul.ulInactvMask |= RG_HQENT_INACTIVE;
475 if(raCb->raState == RGSCH_RA_MSG4_PENDING)
478 ue->rntiLnk = raCb->rntiLnk;
479 /* Update UL Harq process information */
480 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
481 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
483 else if(raCb->raState == RGSCH_RA_MSG4_DONE)
485 ue->rntiLnk = raCb->rntiLnk;
486 /* Update UL Harq process information */
487 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
488 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
489 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
490 rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb);
494 err->errCause = RGSCHERR_RAM_NO_MSG3_RCVD;
496 raCb->dlHqE->ue = NULLP;
501 } /* rgSCHRamRgrUeCfg */
505 * @brief Handler for C-RNTI based contention resolution
509 * Function : rgSCHRamContResCrnti
511 * This function shall be invoked once Msg3 indicates C-RNTI based
512 * contention resolution.This shall indicate the scheduler regarding
513 * C-RNTI based uplink grant.
516 * @param[in,out] RgSchCellCb *cell
517 * @param[in,out] RgSchUeCb *ue
518 * @param[in,out] RgSchRaCb *raCb
523 PRIVATE S16 rgSCHRamContResCrnti
531 PRIVATE S16 rgSCHRamContResCrnti(cell, ue, raCb, err)
538 TfuUlCqiRpt ulCqiRpt;
539 RgSchCmnCell *cellSch= (RgSchCmnCell *)(cell->sc.sch);
540 TRC2(rgSCHRamContResCrnti)
543 /* Fix: syed It is incorrect to copy over msg3HqProc to ueCb's
544 * UL harq proc. In case of Crnti based RACH, ueCb has valid context which
545 * cannot be over written. It was leading to a crash. */
547 rgSCHUtlRecMsg3Alloc(cell, ue, raCb);
549 /* Fix for ccpu00123908: Reset the UL CQI to the cell default value here */
550 ulCqiRpt.isTxPort0 = TRUE;
551 ulCqiRpt.numSubband = 0;
552 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
553 ulCqiRpt.rnti = ue->ueId;
554 /* rg002.301:[ccpu00124018]-MOD- Avoiding hard coding of CQI and retriving from cell config*/
555 ulCqiRpt.wideCqi = cellSch->ul.dfltUlCqi;
556 rgSCHUtlUlCqiInd(cell, ue, &ulCqiRpt);
559 /* Invoke scheduler to indicate UL grant req for contention resolution */
560 rgSCHUtlContResUlGrant(cell, ue, err);
562 if (raCb->phr.pres == TRUE)
564 rgSCHUtlUpdPhr(cell, ue, raCb->phr.val, err);
566 /* No need of raCb any more */
567 rgSCHRamDelRaCb(cell, raCb, TRUE);
570 } /* rgSCHRamContResCrnti */
574 * @brief Handler for CCCH SDU based contention resolution
578 * Function : rgSCHRamContResCcchsdu
580 * This function shall be invoked once Msg3 indicates contention resolution
581 * based on CCCH sdu. This shall update the raCb state to
582 * RGSCH_RA_MSG4_PENDING.
585 * @param[in,out] RgSchRaCb *raCb
590 PRIVATE S16 rgSCHRamContResCcchsdu
596 PRIVATE S16 rgSCHRamContResCcchsdu(cell, raCb)
602 CmLteTimingInfo expTime = {0};
603 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
605 TRC2(rgSCHRamContResCcchsdu)
606 if(raCb->raState != RGSCH_RA_MSG3_PENDING)
608 RLOG_ARG2(L_DEBUG,DBG_CELLID,cell->cellId,
609 "RNTI:%d RaCb in wrong State %d Drop Msg 3",
615 raCb->raState = RGSCH_RA_MSG4_PENDING;
618 if(cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay > 0)
620 /* Set the contension resolution guard timer =
621 Cont Res Timer - Max msg4 Tx Delay */
622 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime,
623 (cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay));
627 /* Schedule the CRI CE in the next Sf itself */
628 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime, 1);
630 raCb->expiryTime = expTime;
631 raCb->contResTmrLnk.node = (PTR)(raCb);
632 cmLListAdd2Tail(&(cell->contResGrdTmrLst), &(raCb->contResTmrLnk));
635 } /* rgSCHRamContResCcchsdu */
639 * @brief Handler for Msg3
643 * Function : rgSCHRamProcMsg3
645 * This function processes the received Msg3 and identifies the type of
646 * contention resolution and act accordingly.
649 * @param[in,out] RgSchCellCb *cell
650 * @param[in,out] RgSchUeCb *ue
651 * @param[in,out] RgSchRaCb *raCb
656 PUBLIC S16 rgSCHRamProcMsg3
665 PUBLIC S16 rgSCHRamProcMsg3(cell, ue, raCb, pdu, err)
673 TRC2(rgSCHRamProcMsg3)
676 /* Update raCb with PHR if received along with Msg3 */
677 if (pdu->ceInfo.bitMask & RGSCH_PHR_CE_PRSNT)
680 raCb->phr.pres = TRUE;
681 raCb->phr.val = pdu->ceInfo.ces.phr;
685 rgSCHRamContResCrnti(cell, ue, raCb, err);
690 if(TRUE == raCb->isEmtcRaCb)
692 /* starting the emtc Contention resolution timer */
693 rgSCHRamEmtcContResCcchsdu(cell,raCb);
698 rgSCHRamContResCcchsdu(cell, raCb);
703 } /* rgSCHRamProcMsg3 */
707 * @brief Handler for Updating Bo received in StaRsp
711 * Function : rgSCHRamUpdtBo
713 * This function shall be invoked by RAM once it receives staRsp on CCCH
715 * @param[in] RgSchCellCb *cell
716 * @param[in,out] RgSchRaCb *raCb
717 * @param[in] RgRguCmnStaRsp *staRsp
722 PUBLIC S16 rgSCHRamUpdtBo
726 RgInfCmnBoRpt *staRsp
729 PUBLIC S16 rgSCHRamUpdtBo(cell, raCb, staRsp)
732 RgInfCmnBoRpt *staRsp;
737 /* Update Bo in RaCb */
738 raCb->dlCcchInfo.bo = (U32)(staRsp->bo);
739 /* SR_RACH_STATS : MSG4 WITH CCCH SDU */
740 rgNumMsg4WithCCCHSdu++;
742 /* add this to the "tobeSchdLst" */
744 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
748 } /* rgSCHRamUpdtBo */
751 * @brief Handler for Msg3 Feedback indication
755 * Function : rgSCHRamMsg3DatInd
757 * This function shall be invoked by TOM once the transmission of Msg4 is
759 * This shall invoke UHM to set ACK for Msg3 reception.
761 * @param[in,out] RgSchRaCb *raCb
766 PUBLIC S16 rgSCHRamMsg3DatInd
771 PUBLIC S16 rgSCHRamMsg3DatInd(raCb)
775 TRC2(rgSCHRamMsg3DatInd)
777 /* SR_RACH_STATS : MSG3 ACK*/
778 rgNumMsg3CrcPassed++;
779 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
780 rgSCHUhmProcMsg3DatInd(&(raCb->msg3HqProc));
783 } /* rgSCHRamMsg3DatInd */
786 * @brief Handler for Msg3 Feedback indication
790 * Function : rgSCHRamMsg3FailureInd
792 * This function shall be invoked by TOM once the transmission of Msg4 is
794 * This shall invoke UHM to set ACK for Msg3 reception.
796 * @param[in,out] RgSchRaCb *raCb
801 PUBLIC S16 rgSCHRamMsg3FailureInd
806 PUBLIC S16 rgSCHRamMsg3FailureInd(raCb)
810 TRC2(rgSCHRamMsg3FailureInd)
812 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
813 rgSCHUhmProcMsg3Failure(&(raCb->msg3HqProc));
816 } /* rgSCHRamMsg3FailureInd */
819 * @brief Handler for Msg4 Feedback indication
823 * Function : rgSCHRamMsg4FdbkInd
825 * This function shall be invoked by TOM once the transmission of Msg4 is
827 * This shall invoke UHM to set ACK for Msg3 reception.
829 * @param[in,out] RgSchRaCb *raCb
834 PUBLIC S16 rgSCHRamMsg4FdbkInd
839 PUBLIC S16 rgSCHRamMsg4FdbkInd(raCb)
843 TRC2(rgSCHRamMsg4FdbkInd)
846 } /* rgSCHRamMsg4FdbkInd */
850 * @brief Handler for Msg4 state updation
854 * Function : rgSCHRamMsg4Done
856 * This function shall be invoked by DHM once the transmission of Msg4 is
857 * done. This shall delete the raCb if there is a valid Ue or if this is to
858 * be deleted. If not this shall update the state of the raCb.
861 * @param[in] RgSchCellCb *cell
862 * @param[in,out] RgSchRaCb *raCb
867 PUBLIC S16 rgSCHRamMsg4Done
873 PUBLIC S16 rgSCHRamMsg4Done(cell, raCb)
878 TRC2(rgSCHRamMsg4Done)
880 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
881 "rgSCHRamMsg4Done(): tmpCRNTI = %u",
884 if(raCb->ue != NULLP)
886 /* Fix : syed Let this funtion decide on releasing
887 * hqP than the caller of this function otherwise sometimes it
888 * might lead to incorrec NDI setting. */
889 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
890 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
891 rgSCHDhmAssgnUeHqEntFrmRaCb(raCb->ue, raCb);
893 if(TRUE == raCb->isEmtcRaCb)
895 rgSCHEmtcUtlUpdCmnNb(raCb);
898 /* MS_FIX :Proceed to CCCH scheduling irrespective of
900 if (raCb->ue->dlCcchInfo.bo)
903 /*if CR-ID Ack has been received ,Add emtc Ue to cchSduUeLst*/
904 if(TRUE == raCb->isEmtcRaCb)
906 rgSCHUtlAddUeToEmtcCcchSduLst(cell, raCb->ue);
911 rgSCHUtlAddUeToCcchSduLst(cell, raCb->ue);
914 /* Rnti shall not be released as Ue exists with this rnti */
915 rgSCHRamDelRaCb(cell, raCb, FALSE);
917 else if(raCb->toDel == TRUE)
919 #ifdef XEON_SPECIFIC_CHANGES
920 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Deleting RacB:%d\n", raCb->tmpCrnti);
922 /* Delete RACB and release RNTI */
923 rgSCHRamDelRaCb(cell, raCb, TRUE);
927 #ifdef XEON_SPECIFIC_CHANGES
928 CM_LOG_DEBUG(CM_LOG_ID_SCH, "Releasing Harq of RacB:%d\n", raCb->tmpCrnti);
930 raCb->raState = RGSCH_RA_MSG4_DONE;
931 /* Release harq process as final feedback is received for Msg4. In other
932 * cases, delRaCb will take care of releasing the harq process */
933 printf("=======Harq process released \n");
934 RLOG_ARG0(L_DEBUG,DBG_CELLID,cell->cellId,
935 "Harq process released ");
936 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
940 } /* rgSCHRamMsg4Done */
944 * @brief Handler for deletion
948 * Function : rgSCHRamDelRaCb
950 * This function shall be invoked whenever a raCb needs to be deleted.
951 * Invoked by both RAM and downlink scheduler
953 * @param[in] RgSchCellCb *cell
954 * @param[in,out] RgSchRaCb *raCb
955 * @param[in] Bool rlsRnti
961 PUBLIC S16 rgSCHRamDelRaCb
968 PUBLIC S16 rgSCHRamDelRaCb(cell, raCb, rlsRnti)
974 Inst inst = cell->instIdx;
976 TRC2(rgSCHRamDelRaCb)
978 /* Delete from all the lists it is enqueued */
979 cmLListDelFrm(&(cell->raInfo.raCbLst),&(raCb->raCbLnk));
981 /*ue Type is EMTC, then Delete the toBeSchedLst and stop the Guard Timer */
982 if(TRUE == raCb->isEmtcRaCb)
984 rgSCHRamEmtcDelRaCb(cell,raCb);
990 if (raCb->schdLnk.node == (PTR)raCb)
992 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
995 else if(raCb->contResTmrLnk.node != NULLP)
997 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
998 raCb->contResTmrLnk.node = NULLP;
1005 rgSCHUtlRlsRnti(cell, raCb->rntiLnk, FALSE, 0);
1008 /* Check if msg4 Hq Proc has been released. If not, release it */
1011 if (raCb->dlHqE->msg4Proc != NULLP)
1013 /* Fix: syed Remove the msg4Proc if it waiting in sf->tbs list for
1015 if ((raCb->dlHqE->msg4Proc->subFrm != NULLP) &&
1016 (raCb->dlHqE->msg4Proc->hqPSfLnk.node != NULLP))
1018 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"TMP CRNTI:%d RACH FAILURE!! "
1019 "msg4proc removed from SF", raCb->tmpCrnti);
1020 rgSCHUtlDlHqPTbRmvFrmTx(raCb->dlHqE->msg4Proc->subFrm,
1021 raCb->dlHqE->msg4Proc, 0, FALSE);
1023 /* Fix: syed Remove the msg4Proc from cell
1024 * msg4Retx Queue. I have used CMN scheduler function
1025 * directly. Please define a new API and call this
1026 * function through that. */
1027 rgSCHCmnDlMsg4ProcRmvFrmRetx(cell, raCb->dlHqE->msg4Proc);
1028 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
1031 /* Mark the raCb pointer in dlHqE to NULLP */
1032 raCb->dlHqE->raCb = NULLP;
1034 rgSCHDhmDelHqEnt(cell, &raCb->dlHqE);
1036 /* Fix: syed Adaptive Msg3 Retx crash. Remove the harqProc
1037 * from adaptive retx List. Free the alloc if it exists. */
1038 if (raCb->msg3HqProc.reTxLnk.node)
1040 //TODO_SID: Need to take care of retxLst
1041 //cmLListDelFrm(raCb->msg3HqProc.reTxAlloc.reTxLst, &raCb->msg3HqProc.reTxLnk);
1042 raCb->msg3HqProc.reTxLnk.node = (PTR)NULLP;
1045 if (raCb->msg3HqProc.alloc)
1047 /* Fix: syed During GPR, please write an API instead of direct
1048 * call to cmn scheduler function */
1049 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
1050 /*ccpu00130356 - MOD- To avoid segmentation problem because of double
1051 free due to recursive calling of rgSCHRamDelRaCb*/
1052 rgSCHRamUlFreeAllocation(&cellUl->ulSfArr[raCb->msg3HqProc.ulSfIdx],
1053 raCb->msg3HqProc.alloc,
1058 if(TRUE == raCb->isEmtcRaCb)
1060 rgSCHEmtcRaInfoFree(cell, raCb);
1063 rgSCHUtlFreeSBuf(inst, (Data **)&raCb, sizeof(RgSchRaCb));
1066 } /* rgSCHRamDelRaCb */
1070 * @brief TTI Handler for RAM module
1074 * Function : rgSCHRamTtiHndlr
1076 * This function shall be invoked upon TtiInd by TOM
1078 * - remove RaReqs added to the queue for a raRnti for which PHY may
1079 * give the requests in the next subframe
1080 * - remove raCbs which are not yet processed once the
1081 * counter for raCb processing expires.
1084 * @param[in,out] RgSchCellCb *cell
1089 PUBLIC S16 rgSCHRamTtiHndlr
1094 PUBLIC S16 rgSCHRamTtiHndlr(cell)
1101 U16 dist; /* Number of frames between raCb's creation and crnt
1108 RgSchRaReqInfo *raReqInfo;
1110 CmLteTimingInfo frm;
1114 TRC2(rgSCHRamTtiHndlr)
1116 crntSfn = cell->crntTime.sfn;
1119 /*Check if Contention resolution guard timer expiring in the TTI*/
1120 rgSCHChkContResGrdTmrExp(cell);
1121 /*Check if Contention resolution timer expiring in the TTI*/
1122 rgSCHChkContResTmrExp(cell);
1124 /*Check if EMTC Contention resolution guard timer expiring in the TTI*/
1125 rgSCHChkEmtcContResGrdTmrExp(cell);
1126 /*Check if EMTC Contention resolution timer expiring in the TTI*/
1127 rgSCHChkEmtcContResTmrExp(cell);
1132 /* Delete the RA requests for which RAR window expired in this subframe
1133 * And were not considered for RAR scheduling*/
1134 winGap = (rgRaPrmblToRaFrmTbl[cell->rachCfg.preambleFormat]-1)+
1135 (cell->rachCfg.raWinSize -1 ) + RGSCH_RARSP_WAIT_PERIOD;
1137 raIdx = (((crntSfn & 1) * RGSCH_MAX_RA_RNTI+ cell->crntTime.subframe
1138 + RG_SCH_CMN_DL_DELTA - winGap)+ RGSCH_RAREQ_ARRAY_SIZE )
1139 % RGSCH_RAREQ_ARRAY_SIZE;
1141 /* Flush the already existing raReqs against the given raRnti */
1143 maxCnt = cell->raInfo.raReqLst[raIdx].count;
1144 for (idx = 0; idx < maxCnt; idx++)
1146 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raIdx].first->node);
1147 cmLListDelFrm(&(cell->raInfo.raReqLst[raIdx]),&(raReqInfo->raReqLstEnt));
1148 /* ccpu00117052 - MOD - Passing double pointer
1149 for proper NULLP assignment*/
1150 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReqInfo,
1151 sizeof(RgSchRaReqInfo));
1154 /* Fixes for RACH handling: Added deletion of queued RaReq */
1155 frm = cell->crntTime;
1156 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
1157 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][frm.subframe] !=
1158 RG_SCH_TDD_UL_SUBFRAME)
1160 raIdx = rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][frm.subframe]-1;
1161 rgSCHRamDelRaReq(cell, cell->crntTime, raIdx);
1165 /* Remove the RACBs which are timed out */
1166 /* ccpu00132536:MOD- racb timeout will be verified in each SFN such that
1167 * the RACB whose processing is not completed in RG_MAX_RA_PRC_FRM
1169 if (cell->crntTime.subframe == 0)
1171 maxCnt = cell->raInfo.raCbLst.count;
1172 for (idx = 0; idx < maxCnt; idx++)
1174 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1175 /* Calculate number of frames between raCb's creation and crnt frame */
1176 raSfn = raCb->timingInfo.sfn;
1177 dist = (crntSfn + (RGSCH_MAX_SFN - raSfn)) % RGSCH_MAX_SFN;
1178 /* Delete RaCbs whose processing is not complete within
1179 * "cell->t300TmrVal" frames */
1180 /* raCb not to be deleted if msg4 is not completed */
1181 /* raCb should not be deleted(RNTI should not be released) if UE is present
1182 * as it means the application still holds the RNTI. raCb will get deleted
1183 * as part of UE deletion. raCb will anyway get deleted without releasing RNTI on success/failure of MSG4*/
1185 if (dist >= cell->t300TmrVal)
1187 if ((raCb->dlHqE->msg4Proc == NULLP) && (raCb->dlHqE->ue == NULLP))
1189 rgSCHRamDelRaCb(cell, raCb, TRUE);
1200 } /* rgSCHRamTtiHndlr */
1204 * @brief Function for handling cell delete
1208 * Function : rgSCHRamFreeCell
1210 * This function shall be invoked whenever a cell needs to be deleted.
1211 * This shall remove raCbs and raReqs stored in cell.
1214 * @param[in,out] RgSchCellCb *cell
1219 PUBLIC S16 rgSCHRamFreeCell
1224 PUBLIC S16 rgSCHRamFreeCell(cell)
1228 RgSchRaReqInfo *raReqInfo;
1232 Inst inst = cell->instIdx;
1240 TRC2(rgSCHRamFreeCell)
1245 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1247 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1248 lstSz = cell->raInfo.maxRaSize * RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1251 /* ccpu00133557- MEM LEAK FIX- Need to free all the nodes in RA Array list */
1252 lstSz = RGSCH_RAREQ_ARRAY_SIZE;
1255 for (idx = 0; idx < lstSz; idx++)
1257 /* Delete and free raReqs stored */
1258 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1259 while(cell->raInfo.raReqLst[idx].count)
1261 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[idx].first->node);
1262 cmLListDelFrm(&(cell->raInfo.raReqLst[idx]),&(raReqInfo->raReqLstEnt));
1263 /* ccpu00117052 - MOD - Passing double pointer
1264 for proper NULLP assignment*/
1265 rgSCHUtlFreeSBuf(inst, (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1270 /* Delete the RACH response list*/
1271 /* ccpu00117052 - MOD - Passing double pointer
1272 for proper NULLP assignment*/
1273 rgSCHUtlFreeSBuf(inst,
1274 (Data **)(&(cell->rachRspLst)), sizeof(RgSchTddRachRspLst) * \
1278 /* Delete raCbs in the "to be scheduled" list */
1279 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1280 while(cell->raInfo.toBeSchdLst.count)
1282 raCb = (RgSchRaCb *)(cell->raInfo.toBeSchdLst.first->node);
1283 /* MSG4 Fix Start */
1285 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
1289 /* Delete raCbs in the "Emtc to be scheduled" list */
1290 if(cell->emtcEnable)
1292 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst(cell);
1296 raCbCnt = cell->raInfo.raCbLst.count;
1298 /* Delete and free raCbs stored */
1299 for (idx = 0; idx < raCbCnt; idx++)
1301 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1302 rgSCHRamDelRaCb(cell, raCb, TRUE);
1306 } /* rgSCHRamFreeCell */
1309 PRIVATE Void rgSCHRamProcContResExp
1315 PRIVATE Void rgSCHRamProcContResExp (cell, raCb)
1320 TRC2(rgSCHRamProcContResExp);
1321 raCb->expiryTime.sfn = RGSCH_CONTRES_EXP;
1325 /* UE exists and RNTI will be released as part of UE DEL */
1326 rgSCHRamDelRaCb(cell, raCb, FALSE);
1330 /* Calling Release RNTI, which would perform Racb deletion
1331 * RNTI removal and RNTI release indication to MAC. */
1332 /* Delete RACB and release RNTI */
1333 rgSCHRamDelRaCb(cell, raCb, TRUE);
1339 PRIVATE Void rgSCHRamProcContResGrdExp
1345 PRIVATE Void rgSCHRamProcContResGrdExp (cell, raCb)
1350 TRC2(rgSCHRamProcContResGrdExp)
1353 /*Guard timer has expired, schedule only the contention REsolution CE with
1355 raCb->dlCcchInfo.bo = 0;
1356 /* SR_RACH_STATS : MSG4 WO CCCH SDU */
1357 rgNumMsg4WoCCCHSdu++;
1359 /* add this to the "tobeSchdLst" */
1360 raCb->schdLnk.node = (PTR)(raCb);
1362 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
1363 raCb->contResTmrLnk.node = NULLP;
1365 /* MSG4 Fix Start */
1366 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,
1367 "Con Res Grd Tmr exp RNTI:%d",
1368 raCb->rntiLnk->rnti);
1369 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
1375 * @brief Check the Contention Resolution Guard Timer Expiry.
1379 * Function: rgSCHChkContResTmrExp
1382 * Invoked by: Scheduler
1383 * @param[in] RgSchCellCb *cell
1389 PRIVATE Void rgSCHChkContResTmrExp
1394 PRIVATE Void rgSCHChkContResTmrExp(cell)
1398 CmLList *chkLnk = NULLP;
1399 RgSchRaCb *raCb = NULLP;
1401 TRC2(rgSCHChkContResTmrExp)
1403 chkLnk = cmLListFirst(&(cell->contResTmrLst));
1405 for (; chkLnk; chkLnk = chkLnk->next)
1407 raCb = (RgSchRaCb *)(chkLnk->node);
1409 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1411 /*If timer expired, call the handler function*/
1412 rgSCHRamProcContResExp(cell, raCb);
1414 /*Fix: Need to traverse till end of list as the entries may not be in ascending order*/
1422 * @brief Check the Contention Resolution Guard Timer Expiry.
1426 * Function: rgSCHChkContResGrdTmrExp
1429 * Invoked by: Scheduler
1430 * @param[in] RgSchCellCb *cell
1436 PRIVATE Void rgSCHChkContResGrdTmrExp
1441 PRIVATE Void rgSCHChkContResGrdTmrExp(cell)
1445 CmLList *chkLnk = NULLP;
1446 RgSchRaCb *raCb = NULLP;
1448 TRC2(rgSCHChkContResGrdTmrExp)
1450 chkLnk = cmLListFirst(&(cell->contResGrdTmrLst));
1452 /*[ccpu00131941]-MOD-List traversal should be done using the listCp */
1453 for (; chkLnk; chkLnk = cmLListNext(&cell->contResGrdTmrLst))
1455 raCb = (RgSchRaCb *)(chkLnk->node);
1457 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1459 /*If timer expired, call the handler function*/
1460 rgSCHRamProcContResGrdExp(cell, raCb);
1471 * @brief Function for handling RACH Request deletion
1475 * Function : rgSCHRamDelRaReq
1477 * This function shall be invoked to delete the RACH Requests
1478 * that is not scheduled within the RA window size.
1481 * @param[in,out] RgSchCellCb *cell
1482 * @param[in] CmLteTimingInfo timingInfo
1483 * @param[in] U8 raIdx
1488 PUBLIC S16 rgSCHRamDelRaReq
1491 CmLteTimingInfo timingInfo,
1495 PUBLIC S16 rgSCHRamDelRaReq(cell, timingInfo, raIdx)
1497 CmLteTimingInfo timingInfo;
1502 RgSchTddRachRspLst *rachRsp;
1506 RgSchRaReqInfo *raReqInfo;
1512 TRC2(rgSCHRamDelRaReq)
1515 rachRsp = &cell->rachRspLst[raIdx];
1516 /* Get the SFN Index to be deleted */
1517 calcSfn = timingInfo.sfn - rachRsp->delInfo.sfnOffset;
1520 sfnIdx = (calcSfn + RGSCH_MAX_SFN) % cell->raInfo.maxRaSize;
1527 /* Iterate through all the subframes to be delted in the SFN */
1528 for(subfrmIdx=0; subfrmIdx < rachRsp->delInfo.numSubfrms; subfrmIdx++)
1530 subfrm = rachRsp->delInfo.subframe[subfrmIdx];
1531 /* Get the subframe Index to be deleted */
1532 /* Fixes for RACH handling in TDD:
1533 * Corrected the computation of raRntiIdx
1535 raRntiIdx = ((sfnIdx % cell->raInfo.maxRaSize) * \
1536 RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1537 RGSCH_NUM_SUB_FRAMES) + subfrm;
1539 /* Iterate through all the RNTIs in the subframe */
1540 for(i=0; i < RGSCH_MAX_RA_RNTI_PER_SUBFRM; i++)
1542 raRnti = raRntiIdx + (i*RGSCH_NUM_SUB_FRAMES);
1543 for (idx = 0; idx < cell->raInfo.raReqLst[raRnti].count; idx++)
1546 (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raRnti].first->node);
1547 cmLListDelFrm(&(cell->raInfo.raReqLst[raRnti]),
1548 &(raReqInfo->raReqLstEnt));
1549 /* ccpu00117052 - MOD - Passing double pointer
1550 for proper NULLP assignment*/
1551 rgSCHUtlFreeSBuf(cell->instIdx,
1552 (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1563 PUBLIC S16 rgSCHRamAddToRaInfoSchdLst
1569 PUBLIC S16 rgSCHRamAddToRaInfoSchdLst(cell, raCb)
1574 CmLteTimingInfo expTime ={0};
1575 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
1577 TRC2(rgSCHRamAddToRaInfoSchdLst)
1579 /*Fix: This can be called even when guard timer is not expired.
1580 * In this case CR timer expiry should be guard timer expiry time + Guard timer time*/
1581 RG_SCH_ADD_TO_CRNT_TIME(raCb->expiryTime, expTime, cellSch->dl.msg4TxDelay);
1582 raCb->expiryTime = expTime;
1583 raCb->schdLnk.node = (PTR)(raCb);
1584 cmLListAdd2Tail(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1585 raCb->contResTmrLnk.node = (PTR)(raCb);
1586 cmLListAdd2Tail(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1588 } /* rgSCHRamAddToRaInfoSchdLst */
1593 PUBLIC S16 rgSCHRamRmvFrmRaInfoSchdLst
1599 PUBLIC S16 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb)
1604 TRC2(rgSCHRamRmvFrmRaInfoSchdLst)
1606 cmLListDelFrm(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1607 raCb->schdLnk.node = NULLP;
1608 cmLListDelFrm(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1609 raCb->contResTmrLnk.node = NULLP;
1611 } /* rgSCHRamRmvFrmRaInfoSchdLst */
1615 /***********************************************************
1617 * Func : rgSCHRamUlFreeAllocation
1619 * Desc : Free an allocation - invokes UHM and releases
1628 **********************************************************/
1630 PRIVATE Void rgSCHRamUlFreeAllocation
1633 RgSchUlAlloc *alloc,
1639 PRIVATE Void rgSCHRamUlFreeAllocation(sf, alloc, cell,isEmtc)
1641 RgSchUlAlloc *alloc;
1646 TRC2(rgSCHRamUlFreeAllocation);
1648 rgSCHUhmFreeProc(alloc->hqProc, cell);
1651 rgSCHUtlUlAllocRls(sf, alloc);
1656 /**********************************************************************
1659 **********************************************************************/