f0bf4e79d9ee31fa99589b8e660a2bbb282dfcd7
[o-du/l2.git] / src / 5gnrsch / sch.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /************************************************************************
20  
21      Name:     sch.c
22   
23      Type:     C source file
24   
25      Desc:     C source code for scheduler fucntions
26   
27      File:     sch.c
28   
29 **********************************************************************/
30
31 /** @file sch.c
32 @brief This file implements the schedulers main access to MAC layer code.
33 */
34 #include "common_def.h" 
35 #include "du_app_mac_inf.h"
36 #include "lrg.h"
37 #include "tfu.h"
38 #include "du_log.h"
39 #include "rgr.h"
40 #include "rg_sch_inf.h"
41 #include "rg_sch.h"
42
43 #include "tfu.x"           /* TFU types */
44 #include "lrg.x"           /* layer management typedefs for MAC */
45 #include "rgr.x"           /* layer management typedefs for MAC */
46 #include "rg_sch_inf.x"         /* typedefs for Scheduler */
47 #include "mac_sch_interface.h"
48 #include "sch.h"
49 #include "sch_utils.h"
50
51 void SchFillCfmPst(Pst *reqPst,Pst *cfmPst,RgMngmt *cfm);
52
53 /* local defines */
54 SchCellCfgCfmFunc SchCellCfgCfmOpts[] = 
55 {
56    packSchCellCfgCfm,     /* LC */
57    MacProcSchCellCfgCfm,  /* TC */
58    packSchCellCfgCfm      /* LWLC */
59 };
60
61 SchSliceCfgRspFunc SchSliceCfgRspOpts[] =
62 {
63    packSchSliceCfgRsp,     /* LC */
64    MacProcSchSliceCfgRsp,  /* TC */
65    packSchSliceCfgRsp      /* LWLC */
66
67 };
68
69 SchSliceReCfgRspFunc SchSliceReCfgRspOpts[] =
70 {
71    packSchSliceReCfgRsp,     /* LC */
72    MacProcSchSliceReCfgRsp,  /* TC */
73    packSchSliceReCfgRsp      /* LWLC */
74 };
75 /**
76  * @brief Task Initiation function. 
77  *
78  * @details
79  *
80  *     Function : schActvInit
81  *     
82  *     This function is supplied as one of parameters during MAC's 
83  *     task registration. MAC will invoke this function once, after
84  *     it creates and attaches this TAPA Task to a system task.
85  *     
86  *  @param[in]  Ent Entity, the entity ID of this task.     
87  *  @param[in]  Inst Inst, the instance ID of this task.
88  *  @param[in]  Region Region, the region ID registered for memory 
89  *              usage of this task.
90  *  @param[in]  Reason Reason.
91  *  @return  int
92  *      -# ROK
93  **/
94 uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
95 {
96    Inst inst = (instId  - SCH_INST_START);
97
98    /* Initialize the MAC TskInit structure to zero */
99    memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
100
101    /* Initialize the MAC TskInit with received values */
102    schCb[inst].schInit.ent = entity;
103    schCb[inst].schInit.inst = inst;
104    schCb[inst].schInit.region = region;
105    schCb[inst].schInit.pool = 0;
106    schCb[inst].schInit.reason = reason;
107    schCb[inst].schInit.cfgDone = FALSE;
108    schCb[inst].schInit.acnt = FALSE;
109    schCb[inst].schInit.usta = FALSE;
110    schCb[inst].schInit.trc = FALSE;
111    schCb[inst].schInit.procId = ODU_GET_PROCID();
112
113    return ROK;
114 } /* schActvInit */
115
116 /**
117  * @brief Scheduler instance Configuration Handler. 
118  *
119  * @details
120  *
121  *     Function : SchInstCfg
122  *     
123  *     This function in called by SchProcGenCfgReq(). It handles the
124  *     general configurations of the scheduler instance. Returns
125  *     reason for success/failure of this function.
126  *     
127  *  @param[in]  RgCfg *cfg, the Configuaration information 
128  *  @return  uint16_t
129  *      -# LCM_REASON_NOT_APPL 
130  *      -# LCM_REASON_INVALID_MSGTYPE
131  *      -# LCM_REASON_MEM_NOAVAIL
132  **/
133 uint8_t SchInstCfg(RgCfg *cfg, Inst  dInst)
134 {
135    uint16_t ret = LCM_REASON_NOT_APPL;
136    Inst     inst = (dInst - SCH_INST_START);
137
138    DU_LOG("\nDEBUG  -->  SCH : Entered SchInstCfg()");
139    /* Check if Instance Configuration is done already */
140    if (schCb[inst].schInit.cfgDone == TRUE)
141    {
142       return LCM_REASON_INVALID_MSGTYPE;
143    }
144    /* Update the Pst structure for LM interface */
145    memcpy(&schCb[inst].schInit.lmPst,
146          &cfg->s.schInstCfg.genCfg.lmPst,
147          sizeof(Pst));
148
149    schCb[inst].schInit.inst = inst;
150    schCb[inst].schInit.lmPst.srcProcId = schCb[inst].schInit.procId;
151    schCb[inst].schInit.lmPst.srcEnt = schCb[inst].schInit.ent;
152    schCb[inst].schInit.lmPst.srcInst = schCb[inst].schInit.inst +
153       SCH_INST_START;
154    schCb[inst].schInit.lmPst.event = EVTNONE;
155
156    schCb[inst].schInit.region = cfg->s.schInstCfg.genCfg.mem.region;
157    schCb[inst].schInit.pool = cfg->s.schInstCfg.genCfg.mem.pool;
158    schCb[inst].genCfg.tmrRes = cfg->s.schInstCfg.genCfg.tmrRes;
159 #ifdef LTE_ADV
160    schCb[inst].genCfg.forceCntrlSrbBoOnPCel =  cfg->s.schInstCfg.genCfg.forceCntrlSrbBoOnPCel;
161    schCb[inst].genCfg.isSCellActDeactAlgoEnable =  cfg->s.schInstCfg.genCfg.isSCellActDeactAlgoEnable;
162 #endif
163    schCb[inst].genCfg.startCellId    = cfg->s.schInstCfg.genCfg.startCellId;
164
165    /* Initialzie the timer queue */   
166    memset(&schCb[inst].tmrTq, 0, sizeof(CmTqType) * SCH_TQ_SIZE);
167    /* Initialize the timer control point */
168    memset(&schCb[inst].tmrTqCp, 0, sizeof(CmTqCp));
169    schCb[inst].tmrTqCp.tmrLen = RGSCH_TQ_SIZE;
170
171    /* SS_MT_TMR needs to be enabled as schActvTmr needs instance information */
172    /* Timer Registration request to system services */
173    if (ODU_REG_TMR_MT(schCb[inst].schInit.ent, dInst,
174             (int)schCb[inst].genCfg.tmrRes, schActvTmr) != ROK)
175    {
176       DU_LOG("\nERROR  -->  SCH : SchInstCfg(): Failed to "
177             "register timer.");
178       return (LCM_REASON_MEM_NOAVAIL);
179    }   
180               
181    /* Set Config done in TskInit */
182    schCb[inst].schInit.cfgDone = TRUE;
183    DU_LOG("\nINFO   -->  SCH : Scheduler gen config done");
184
185    return ret;
186 }
187
188 /**
189  * @brief Layer Manager Configuration request handler. 
190  *
191  * @details
192  *
193  *     Function : SchProcGenCfgReq
194  *     
195  *     This function handles the configuration
196  *     request received at scheduler instance from the Layer Manager.
197  *     -# Based on the cfg->hdr.elmId.elmnt value it invokes one of the
198  *        functions rgHdlGenCfg() or rgHdlSapCfg().
199  *     -# Invokes RgMiLrgSchCfgCfm() to send back the confirmation to the LM.
200  *     
201  *  @param[in]  Pst *pst, the post structure     
202  *  @param[in]  RgMngmt *cfg, the configuration parameter's structure
203  *  @return  S16
204  *      -# ROK
205  **/
206 uint8_t SchProcGenCfgReq(Pst *pst, RgMngmt *cfg)
207 {
208    uint8_t   ret = LCM_PRIM_OK;
209    uint16_t  reason = LCM_REASON_NOT_APPL;
210    RgMngmt   cfm;
211    Pst       cfmPst;
212
213 #ifdef CALL_FLOW_DEBUG_LOG
214    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : GENERAL_CFG_REQ\n");
215 #endif
216
217    if(pst->dstInst < SCH_INST_START)
218    {
219       DU_LOG("\nERROR  -->  SCH : Invalid inst ID");
220       DU_LOG("\nERROR  -->  SCH : SchProcGenCfgReq(): "
221             "pst->dstInst=%d SCH_INST_START=%d", pst->dstInst,SCH_INST_START); 
222       return ROK;
223    }
224    DU_LOG("\nINFO   -->  SCH : Received scheduler gen config");
225    /* Fill the post structure for sending the confirmation */
226    memset(&cfmPst, 0 , sizeof(Pst));
227    SchFillCfmPst(pst, &cfmPst, cfg);
228
229    memset(&cfm, 0, sizeof(RgMngmt));
230
231 #ifdef LMINT3
232    cfm.hdr.transId =
233       cfg->hdr.transId;
234 #endif
235
236    cfm.hdr.elmId.elmnt = cfg->hdr.elmId.elmnt;
237    switch(cfg->hdr.elmId.elmnt)
238    {
239       case STSCHINST:
240          reason = SchInstCfg(&cfg->t.cfg,pst->dstInst );
241          break;
242       default:
243          ret = LCM_PRIM_NOK;
244          reason = LCM_REASON_INVALID_ELMNT;
245          DU_LOG("\nERROR  -->  SCH : Invalid Elmnt=%d", cfg->hdr.elmId.elmnt);
246          break;
247    }
248
249    if (reason != LCM_REASON_NOT_APPL)
250    {
251       ret = LCM_PRIM_NOK;
252    }
253
254    cfm.cfm.status = ret;
255    cfm.cfm.reason = reason;
256
257    SchSendCfgCfm(&cfmPst, &cfm);
258    /*   SCH_FREE(pst->region, pst->pool, (Data *)cfg, sizeof(RgMngmt)); */
259
260    return ROK;
261 }/*-- SchProcGenCfgReq --*/
262
263 /**
264  * @brief slot indication from MAC to SCH.
265  *
266  * @details
267  *
268  *     Function : MacSchSlotInd 
269  *      
270  *      This API is invoked by PHY to indicate slot indication to Scheduler for
271  *      a cell.
272  *           
273  *  @param[in]  Pst            *pst
274  *  @param[in]  SlotTimingInfo    *slotInd
275  *  @return  S16
276  *      -# ROK 
277  *      -# RFAILED 
278  **/
279 uint8_t MacSchSlotInd(Pst *pst, SlotTimingInfo *slotInd)
280 {
281    Inst  inst = pst->dstInst-SCH_INST_START;
282
283 #ifdef CALL_FLOW_DEBUG_LOG
284    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SLOT_IND_TO_SCH\n");
285 #endif
286
287    schProcessSlotInd(slotInd, inst);
288
289    return ROK;
290 }  /* MacSchSlotInd */
291
292 /*******************************************************************
293  *
294  * @brief Processes Rach indication from MAC 
295  *
296  * @details
297  *
298  *    Function : MacSchRachInd
299  *
300  *    Functionality:
301  *      Processes Rach indication from MAC
302  *
303  * @params[in] 
304  * @return ROK     - success
305  *         RFAILED - failure
306  *
307  * ****************************************************************/
308 uint8_t MacSchRachInd(Pst *pst, RachIndInfo *rachInd)
309 {
310    Inst  inst = pst->dstInst-SCH_INST_START;
311
312 #ifdef CALL_FLOW_DEBUG_LOG
313    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_RACH_IND_TO_SCH\n");
314 #endif
315
316    DU_LOG("\nINFO  -->  SCH : Received Rach indication");
317    schProcessRachInd(rachInd, inst);
318    return ROK;
319 }
320
321 /*******************************************************************
322  *
323  * @brief Processes CRC indication from MAC 
324  *
325  * @details
326  *
327  *    Function : MacSchCrcInd
328  *
329  *    Functionality:
330  *      Processes CRC indication from MAC
331  *
332  * @params[in] Post structure
333  *             Crc Indication
334  * @return ROK     - success
335  *         RFAILED - failure
336  *
337  * ****************************************************************/
338 uint8_t MacSchCrcInd(Pst *pst, CrcIndInfo *crcInd)
339 {
340 #ifdef CALL_FLOW_DEBUG_LOG
341    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_CRC_IND_TO_SCH\n");
342 #endif
343
344    switch(crcInd->crcInd[0])
345    {
346       case CRC_FAILED:
347          DU_LOG("\nDEBUG  -->  SCH : Received CRC indication. CRC Status [FAILURE]");
348          break;
349       case CRC_PASSED:
350          DU_LOG("\nDEBUG  -->  SCH : Received CRC indication. CRC Status [PASS]");
351          break;
352       default:
353          DU_LOG("\nDEBUG  -->  SCH : Invalid CRC state %d", crcInd->crcInd[0]);
354          return RFAILED;
355    }
356    return ROK;
357 }
358
359 #ifdef NR_TDD
360 /**
361  *@brief Returns TDD periodicity in micro seconds
362  *
363  * @details
364  * 
365  * Function : schGetPeriodicityInMsec 
366  * 
367  * This API retunrs TDD periodicity in micro seconds
368  * 
369  * @param[in] DlUlTxPeriodicity 
370  * @return  periodicityInMsec
371  * **/
372
373 uint16_t schGetPeriodicityInMsec(DlUlTxPeriodicity tddPeriod)
374 {
375    uint16_t  periodicityInMsec = 0;
376    switch(tddPeriod)
377    {
378       case TX_PRDCTY_MS_0P5:
379       {
380          periodicityInMsec = 500;
381          break;
382       }
383       case TX_PRDCTY_MS_0P625:
384       {
385          periodicityInMsec = 625;
386          break;
387       }
388       case TX_PRDCTY_MS_1:
389       {
390          periodicityInMsec = 1000;
391          break;
392       }
393       case TX_PRDCTY_MS_1P25:
394       {
395          periodicityInMsec = 1250;
396          break;
397       }
398       case TX_PRDCTY_MS_2:
399       {
400          periodicityInMsec = 2000;
401          break;
402       }
403       case TX_PRDCTY_MS_2P5:
404       {
405          periodicityInMsec = 2500;
406          break;
407       }
408       case TX_PRDCTY_MS_5:
409       {
410          periodicityInMsec = 5000;
411          break;
412       }
413       case TX_PRDCTY_MS_10:
414       {
415          periodicityInMsec = 10000;
416          break;
417       }
418       default:
419       {
420          DU_LOG("\nERROR  -->  SCH : Invalid DlUlTxPeriodicity:%d", tddPeriod);
421       }
422    }
423
424    return periodicityInMsec;
425 }
426
427
428 /**
429  * @brief init TDD slot config 
430  *
431  * @details
432  *
433  *     Function : schInitTddSlotCfg 
434  *      
435  *      This API is invoked after receiving schCellCfg
436  *           
437  *  @param[in]  schCellCb *cell
438  *  @param[in]  SchCellCfg *schCellCfg
439  *  @return  void
440  **/
441 void schInitTddSlotCfg(SchCellCb *cell, SchCellCfg *schCellCfg)
442 {
443    uint16_t periodicityInMicroSec = 0;
444    int8_t slotIdx, symbIdx;
445
446    periodicityInMicroSec = schGetPeriodicityInMsec(schCellCfg->tddCfg.tddPeriod);
447    cell->numSlotsInPeriodicity = (periodicityInMicroSec * pow(2, schCellCfg->numerology))/1000;
448    cell->slotFrmtBitMap = 0;
449    cell->symbFrmtBitMap = 0;
450    for(slotIdx = cell->numSlotsInPeriodicity-1; slotIdx >= 0; slotIdx--)
451    {
452       symbIdx = 0;
453       /* If the first and last symbol are the same, the entire slot is the same type */
454       if((schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx] == schCellCfg->tddCfg.slotCfg[slotIdx][MAX_SYMB_PER_SLOT-1]) &&
455               schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx] != FLEXI_SLOT)
456       {
457          switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
458          {
459             case DL_SLOT:
460             {
461                /*BitMap to be set to 00 */
462                cell->slotFrmtBitMap = (cell->slotFrmtBitMap<<2);
463                break;
464             }
465             case UL_SLOT:
466             {
467                /*BitMap to be set to 01 */
468                cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (UL_SLOT));
469                break;
470             }
471             default:
472                DU_LOG("\nERROR  -->  SCH : Invalid slot Config in schInitTddSlotCfg");
473            }
474          continue;
475       }
476       /* slot config is flexible. First set slotBitMap to 10 */
477       cell->slotFrmtBitMap = ((cell->slotFrmtBitMap<<2) | (FLEXI_SLOT));
478
479       /* Now set symbol bitmap */ 
480       for(symbIdx = MAX_SYMB_PER_SLOT-1; symbIdx >= 0; symbIdx--)
481       {
482          switch(schCellCfg->tddCfg.slotCfg[slotIdx][symbIdx])
483          {
484             case DL_SLOT:
485             {
486                /*symbol BitMap to be set to 00 */
487                cell->symbFrmtBitMap = (cell->symbFrmtBitMap<<2);
488                break;
489             }
490             case UL_SLOT:
491             {
492                /*symbol BitMap to be set to 01 */
493                cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (UL_SLOT));
494                break;
495             }
496             case FLEXI_SLOT:
497             {
498                /*symbol BitMap to be set to 10 */
499                cell->symbFrmtBitMap = ((cell->symbFrmtBitMap<<2) | (FLEXI_SLOT));
500                break;
501             }
502             default:
503                DU_LOG("\nERROR  -->  SCH : Invalid slot Config in schInitTddSlotCfg");
504          }
505       }
506    }
507 }
508 #endif
509
510 /**
511  * @brief Fill SSB start symbol
512  *
513  * @details
514  *
515  *     Function : fillSsbStartSymb 
516  *      
517  *      This API stores SSB start index per beam
518  *           
519  *  @param[in]  SchCellCb     *cellCb
520  *  @return  int
521  *      -# ROK 
522  *      -# RFAILED 
523  **/
524 void fillSsbStartSymb(SchCellCb *cellCb)
525 {
526    uint8_t cnt, scs, symbIdx, ssbStartSymbArr[SCH_MAX_SSB_BEAM];
527
528    scs = cellCb->cellCfg.ssbSchCfg.scsCommon;
529
530    memset(ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
531    symbIdx = 0;
532    /* Determine value of "n" based on Section 4.1 of 3GPP TS 38.213 */
533    switch(scs)
534    {
535       case SCS_15KHZ:
536          {
537             if(cellCb->cellCfg.dlFreq <= 300000)
538                cnt = 2;/* n = 0, 1 */
539             else
540                cnt = 4; /* n = 0, 1, 2, 3 */
541             for(uint8_t idx=0; idx<cnt; idx++)
542             {
543                /* start symbol determined using {2, 8} + 14n */
544                ssbStartSymbArr[symbIdx++] = 2 +  MAX_SYMB_PER_SLOT*idx;
545                ssbStartSymbArr[symbIdx++] = 8 +  MAX_SYMB_PER_SLOT*idx;
546             }
547          }
548          break;
549       case SCS_30KHZ:
550          {
551             if(cellCb->cellCfg.dlFreq <= 300000)
552                cnt = 1;/* n = 0 */
553             else
554                cnt = 2; /* n = 0, 1 */
555             for(uint8_t idx=0; idx<cnt; idx++)
556             {
557                /* start symbol determined using {4, 8, 16, 20} + 28n */
558                ssbStartSymbArr[symbIdx++] = 4 +  MAX_SYMB_PER_SLOT*idx;
559                ssbStartSymbArr[symbIdx++] = 8 +  MAX_SYMB_PER_SLOT*idx;
560                ssbStartSymbArr[symbIdx++] = 16 +  MAX_SYMB_PER_SLOT*idx;
561                ssbStartSymbArr[symbIdx++] = 20 +  MAX_SYMB_PER_SLOT*idx;
562             }
563          }
564          break;
565       default:
566          DU_LOG("\nERROR  -->  SCH : SCS %d is currently not supported", scs);
567    }
568    memset(cellCb->ssbStartSymbArr, 0, sizeof(SCH_MAX_SSB_BEAM));
569    memcpy(cellCb->ssbStartSymbArr, ssbStartSymbArr, SCH_MAX_SSB_BEAM);
570
571 }
572
573
574 /**
575  * @brief init cellCb based on cellCfg
576  *
577  * @details
578  *
579  *     Function : schInitCellCb 
580  *      
581  *      This API is invoked after receiving schCellCfg
582  *           
583  *  @param[in]  schCellCb *cell
584  *  @param[in]  SchCellCfg *schCellCfg
585  *  @return  int
586  *      -# ROK 
587  *      -# RFAILED 
588  **/
589 uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg)
590 {
591    SchCellCb *cell= NULLP;
592    SCH_ALLOC(cell, sizeof(SchCellCb));
593    if(!cell)
594    {
595       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
596       return RFAILED;
597    }
598
599    cell->cellId = schCellCfg->cellId; 
600    cell->instIdx = inst;
601    switch(schCellCfg->numerology)
602    {
603       case SCH_NUMEROLOGY_0:
604          {
605             cell->numSlots = SCH_MU0_NUM_SLOTS;
606          }
607          break;
608       case SCH_NUMEROLOGY_1:
609          {
610             cell->numSlots = SCH_MU1_NUM_SLOTS;
611          }
612          break;
613       case SCH_NUMEROLOGY_2:
614          {
615             cell->numSlots = SCH_MU2_NUM_SLOTS;
616          }
617          break;
618       case SCH_NUMEROLOGY_3:
619          {
620             cell->numSlots = SCH_MU3_NUM_SLOTS;
621          }
622          break;
623       case SCH_NUMEROLOGY_4:
624          {
625             cell->numSlots = SCH_MU4_NUM_SLOTS;
626          }
627          break;
628       default:
629          DU_LOG("\nERROR  -->  SCH : Numerology %d not supported", schCellCfg->numerology);
630    }
631 #ifdef NR_TDD
632    schInitTddSlotCfg(cell, schCellCfg);   
633 #endif
634
635    SCH_ALLOC(cell->schDlSlotInfo, cell->numSlots * sizeof(SchDlSlotInfo*));
636    if(!cell->schDlSlotInfo)
637    {
638       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schDlSlotInfo");
639       return RFAILED;
640    }
641
642    SCH_ALLOC(cell->schUlSlotInfo, cell->numSlots * sizeof(SchUlSlotInfo*));
643    if(!cell->schUlSlotInfo)
644    {
645       DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb for schUlSlotInfo");
646       return RFAILED;
647    }
648
649    for(uint8_t idx=0; idx<cell->numSlots; idx++)
650    {
651       SchDlSlotInfo *schDlSlotInfo;
652       SchUlSlotInfo *schUlSlotInfo;
653
654       /* DL Alloc */
655       SCH_ALLOC(schDlSlotInfo, sizeof(SchDlSlotInfo));
656       if(!schDlSlotInfo)
657       {
658          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
659          return RFAILED;
660       }
661
662       /* UL Alloc */
663       SCH_ALLOC(schUlSlotInfo, sizeof(SchUlSlotInfo));
664       if(!schUlSlotInfo)
665       {
666          DU_LOG("\nERROR  -->  SCH : Memory allocation failed in schInitCellCb");
667          return RFAILED;
668       }
669
670       schInitDlSlot(schDlSlotInfo);
671       schInitUlSlot(schUlSlotInfo);
672
673       cell->schDlSlotInfo[idx] = schDlSlotInfo;
674       cell->schUlSlotInfo[idx] = schUlSlotInfo;
675
676    }
677    cell->firstSsbTransmitted = false;
678    cell->firstSib1Transmitted = false;
679    fillSsbStartSymb(cell);
680    cmLListInit(&cell->ueToBeScheduled);
681    schCb[inst].cells[inst] = cell;
682
683    DU_LOG("\nINFO  -->  SCH : Cell init completed for cellId:%d", cell->cellId);
684
685    return ROK;   
686 }
687
688 /**
689  * @brief Fill SIB1 configuration
690  *
691  * @details
692  *
693  *     Function : fillSchSib1Cfg
694  *
695  *     Fill SIB1 configuration
696  *
697  *  @param[in]  uint8_t bandwidth : total available bandwidth
698  *              uint8_t numSlots : total slots per SFN
699  *              SchSib1Cfg *sib1SchCfg : cfg to be filled
700  *              uint16_t pci : physical cell Id
701  *              uint8_t offsetPointA : offset
702  *  @return  void
703  **/
704 void fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots, SchSib1Cfg *sib1SchCfg, uint16_t pci, uint8_t offsetPointA)
705 {
706    uint8_t coreset0Idx = 0;
707    uint8_t searchSpace0Idx = 0;
708    //uint8_t ssbMuxPattern = 0;
709    uint8_t numRbs = 0;
710    uint8_t numSymbols = 0;
711    uint8_t offset = 0;
712    uint8_t oValue = 0;
713    //uint8_t numSearchSpacePerSlot = 0;
714    uint8_t mValue = 0;
715    uint8_t firstSymbol = 0; /* need to calculate using formula mentioned in 38.213 */
716    uint8_t slotIndex = 0;
717    uint8_t FreqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
718    uint16_t tbSize = 0;
719    uint8_t ssbIdx = 0;
720
721    PdcchCfg *pdcch = &(sib1SchCfg->sib1PdcchCfg);
722    PdschCfg *pdsch = &(sib1SchCfg->sib1PdschCfg);
723    BwpCfg *bwp = &(sib1SchCfg->bwp);
724
725    coreset0Idx     = sib1SchCfg->coresetZeroIndex;
726    searchSpace0Idx = sib1SchCfg->searchSpaceZeroIndex;
727
728    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
729    //ssbMuxPattern = coresetIdxTable[coreset0Idx][0];
730    numRbs        = coresetIdxTable[coreset0Idx][1];
731    numSymbols    = coresetIdxTable[coreset0Idx][2];
732    offset        = coresetIdxTable[coreset0Idx][3];
733
734    /* derive the search space params from table 13-11 spec 38.213 */
735    oValue                = searchSpaceIdxTable[searchSpace0Idx][0];
736    //numSearchSpacePerSlot = searchSpaceIdxTable[searchSpace0Idx][1];
737    mValue                = searchSpaceIdxTable[searchSpace0Idx][2];
738    firstSymbol           = searchSpaceIdxTable[searchSpace0Idx][3];
739
740    /* calculate the n0, need to add the formulae, as of now the value is 0 
741     * Need to add the even and odd values of i during configuration 
742     * [(O . 2^u + i . M )  ] mod numSlotsPerSubframe 
743     * assuming u = 0, i = 0, numSlotsPerSubframe = 10
744     * Also, from this configuration, coreset0 is only on even subframe */
745    slotIndex = (int)((oValue*pow(2, mu)) + floor(ssbIdx*mValue))%numSlots;
746    sib1SchCfg->n0 = slotIndex;
747
748    /* fill BWP */
749    switch(bandwidth)
750    {
751       case BANDWIDTH_20MHZ:
752          {
753             bwp->freqAlloc.numPrb = TOTAL_PRB_20MHZ_MU0;
754          }
755          break;
756       case BANDWIDTH_100MHZ:
757          {
758             bwp->freqAlloc.numPrb = TOTAL_PRB_100MHZ_MU1;
759          }
760          break;
761       default:
762          DU_LOG("\nERROR  -->  SCH : Bandwidth %d not supported", bandwidth);
763
764    }
765    bwp->freqAlloc.startPrb = 0;
766    bwp->subcarrierSpacing  = 0;         /* 15Khz */
767    bwp->cyclicPrefix       = 0;              /* normal */
768
769    /* fill the PDCCH PDU */
770    pdcch->coresetCfg.coreSetSize = numRbs;
771    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
772    pdcch->coresetCfg.durationSymbols = numSymbols;
773    
774    /* Fill Bitmap for PRBs in coreset */
775    fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
776    covertFreqDomRsrcMapToIAPIFormat(FreqDomainResource, pdcch->coresetCfg.freqDomainResource);
777
778    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
779    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
780    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
781    pdcch->coresetCfg.coreSetType = 0;
782    pdcch->coresetCfg.shiftIndex = pci;
783    pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */
784    pdcch->numDlDci = 1;
785    pdcch->dci.rnti = SI_RNTI;
786    pdcch->dci.scramblingId = pci;
787    pdcch->dci.scramblingRnti = 0;
788    pdcch->dci.cceIndex = 0;
789    pdcch->dci.aggregLevel = 4;
790    pdcch->dci.beamPdcchInfo.numPrgs = 1;
791    pdcch->dci.beamPdcchInfo.prgSize = 1;
792    pdcch->dci.beamPdcchInfo.digBfInterfaces = 0;
793    pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0;
794    pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0;
795    pdcch->dci.txPdcchPower.powerValue = 0;
796    pdcch->dci.txPdcchPower.powerControlOffsetSS = 0;
797    /* Storing pdschCfg pointer here. Required to access pdsch config while
798       fillig up pdcch pdu */
799    pdcch->dci.pdschCfg = pdsch; 
800
801    /* fill the PDSCH PDU */
802    uint8_t cwCount = 0;
803    pdsch->pduBitmap = 0; /* PTRS and CBG params are excluded */
804    pdsch->rnti = 0xFFFF; /* SI-RNTI */
805    pdsch->pduIndex = 0;
806    pdsch->numCodewords = 1;
807    for(cwCount = 0; cwCount < pdsch->numCodewords; cwCount++)
808    {
809       pdsch->codeword[cwCount].targetCodeRate = 308;
810       pdsch->codeword[cwCount].qamModOrder = 2;
811       pdsch->codeword[cwCount].mcsIndex = sib1SchCfg->sib1Mcs;
812       pdsch->codeword[cwCount].mcsTable = 0; /* notqam256 */
813       pdsch->codeword[cwCount].rvIndex = 0;
814       tbSize = schCalcTbSize(sib1SchCfg->sib1PduLen + TX_PAYLOAD_HDR_LEN);
815       pdsch->codeword[cwCount].tbSize = tbSize;
816    }
817    pdsch->dataScramblingId                   = pci;
818    pdsch->numLayers                          = 1;
819    pdsch->transmissionScheme                 = 0;
820    pdsch->refPoint                           = 0;
821    pdsch->dmrs.dlDmrsSymbPos                 = 4; /* Bitmap value 00000000000100 i.e. using 3rd symbol for PDSCH DMRS */
822    pdsch->dmrs.dmrsConfigType                = 0; /* type-1 */
823    pdsch->dmrs.dlDmrsScramblingId            = pci;
824    pdsch->dmrs.scid                          = 0;
825    pdsch->dmrs.numDmrsCdmGrpsNoData          = 1;
826    pdsch->dmrs.dmrsPorts                     = 0x0001;
827    pdsch->dmrs.mappingType                   = DMRS_MAP_TYPE_A; /* Type-A */
828    pdsch->dmrs.nrOfDmrsSymbols               = NUM_DMRS_SYMBOLS;
829    pdsch->dmrs.dmrsAddPos                    = DMRS_ADDITIONAL_POS;
830
831    pdsch->pdschFreqAlloc.resourceAllocType   = 1; /* RAT type-1 RIV format */
832    /* the RB numbering starts from coreset0, and PDSCH is always above SSB */
833    pdsch->pdschFreqAlloc.freqAlloc.startPrb  = offsetPointA + SCH_SSB_NUM_PRB;
834    pdsch->pdschFreqAlloc.freqAlloc.numPrb    = schCalcNumPrb(tbSize,sib1SchCfg->sib1Mcs, NUM_PDSCH_SYMBOL);
835    pdsch->pdschFreqAlloc.vrbPrbMapping       = 0; /* non-interleaved */
836    pdsch->pdschTimeAlloc.rowIndex            = 1;
837    /* This is Intel's requirement. PDSCH should start after PDSCH DRMS symbol */
838    pdsch->pdschTimeAlloc.timeAlloc.startSymb = 3; /* spec-38.214, Table 5.1.2.1-1 */
839    pdsch->pdschTimeAlloc.timeAlloc.numSymb   = NUM_PDSCH_SYMBOL;
840    pdsch->beamPdschInfo.numPrgs              = 1;
841    pdsch->beamPdschInfo.prgSize              = 1;
842    pdsch->beamPdschInfo.digBfInterfaces      = 0;
843    pdsch->beamPdschInfo.prg[0].pmIdx         = 0;
844    pdsch->beamPdschInfo.prg[0].beamIdx[0]    = 0;
845    pdsch->txPdschPower.powerControlOffset    = 0;
846    pdsch->txPdschPower.powerControlOffsetSS  = 0;
847
848 }
849
850 /**
851  * @brief cell config from MAC to SCH.
852  *
853  * @details
854  *
855  *     Function : macSchCellCfgReq
856  *      
857  *      This API is invoked by MAC to send cell config to SCH
858  *           
859  *  @param[in]  Pst            *pst
860  *  @param[in]  SchCellCfg     *schCellCfg
861  *  @return  int
862  *      -# ROK 
863  *      -# RFAILED 
864  **/
865 uint8_t SchHdlCellCfgReq(Pst *pst, SchCellCfg *schCellCfg)
866 {
867    uint8_t ret = ROK;
868    SchCellCb *cellCb;
869    SchCellCfgCfm schCellCfgCfm;
870    Pst rspPst;
871    Inst inst = pst->dstInst-1; 
872    uint8_t coreset0Idx = 0;
873    uint8_t numRbs = 0;
874    uint8_t offset = 0;
875    uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0};
876    SchPdschConfig pdschCfg;
877
878 #ifdef CALL_FLOW_DEBUG_LOG
879    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SCH_CELL_CFG\n");
880 #endif 
881
882    schInitCellCb(inst, schCellCfg);
883    cellCb = schCb[inst].cells[inst]; //cells is of MAX_CELLS, why inst
884    cellCb->macInst = pst->srcInst;
885
886    /* derive the SIB1 config parameters */
887    fillSchSib1Cfg(schCellCfg->numerology, schCellCfg->bandwidth, cellCb->numSlots,
888          &(schCellCfg->sib1SchCfg), schCellCfg->phyCellId,
889          schCellCfg->ssbSchCfg.ssbOffsetPointA);
890    memcpy(&cellCb->cellCfg, schCellCfg, sizeof(SchCellCfg));
891
892    /* Fill coreset frequencyDomainResource bitmap */
893    coreset0Idx = cellCb->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.coresetId;
894    numRbs = coresetIdxTable[coreset0Idx][1];
895    offset = coresetIdxTable[coreset0Idx][3];
896    fillCoresetFeqDomAllocMap(((cellCb->cellCfg.ssbSchCfg.ssbOffsetPointA - offset)/6), (numRbs/6), freqDomainResource);
897    covertFreqDomRsrcMapToIAPIFormat(freqDomainResource, \
898       cellCb->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc);
899
900    /* Fill K0 - K1 table for common cfg*/ 
901    BuildK0K1Table(cellCb, &cellCb->cellCfg.schInitialDlBwp.k0K1InfoTbl, true, cellCb->cellCfg.schInitialDlBwp.pdschCommon,
902    pdschCfg, DEFAULT_UL_ACK_LIST_COUNT, defaultUlAckTbl);
903    
904    BuildK2InfoTable(cellCb, cellCb->cellCfg.schInitialUlBwp.puschCommon.timeDomRsrcAllocList,\
905    cellCb->cellCfg.schInitialUlBwp.puschCommon.numTimeDomRsrcAlloc, &cellCb->cellCfg.schInitialUlBwp.msg3K2InfoTbl, \
906    &cellCb->cellCfg.schInitialUlBwp.k2InfoTbl);
907    /* Initializing global variables */
908    cellCb->actvUeBitMap = 0;
909    cellCb->boIndBitMap = 0;
910
911    /* Fill and send Cell config confirm */
912    memset(&rspPst, 0, sizeof(Pst));
913    FILL_PST_SCH_TO_MAC(rspPst, pst->dstInst);
914    rspPst.event = EVENT_SCH_CELL_CFG_CFM;
915
916    schCellCfgCfm.cellId = schCellCfg->cellId; 
917    schCellCfgCfm.rsp = RSP_OK;
918
919    ret = (*SchCellCfgCfmOpts[rspPst.selector])(&rspPst, &schCellCfgCfm);
920    return ret;
921
922 }
923
924 /*******************************************************************
925  *
926  * @brief Processes DL RLC BO info from MAC
927  *
928  * @details
929  *
930  *    Function : MacSchDlRlcBoInfo
931  *
932  *    Functionality:
933  *       Processes DL RLC BO info from MAC
934  *
935  * @params[in] 
936  * @return ROK     - success
937  *         RFAILED - failure
938  *
939  * ****************************************************************/
940 uint8_t MacSchDlRlcBoInfo(Pst *pst, DlRlcBoInfo *dlBoInfo)
941 {
942    uint8_t  lcId = 0;
943    uint16_t ueId = 0;
944    bool isLcIdValid = false;
945    SchUeCb *ueCb = NULLP;
946    SchCellCb *cell = NULLP;
947    Inst  inst = pst->dstInst-SCH_INST_START;
948    CmLListCp *lcLL = NULLP;
949
950 #ifdef CALL_FLOW_DEBUG_LOG
951    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_DL_RLC_BO_INFO_TO_SCH\n");
952 #endif
953
954    DU_LOG("\nDEBUG  -->  SCH : Received RLC BO Status indication LCId [%d] BO [%d]", dlBoInfo->lcId, dlBoInfo->dataVolume);
955    cell = schCb[inst].cells[inst];
956
957    if(cell == NULLP)
958    {
959       DU_LOG("\nERROR  -->  SCH : MacSchDlRlcBoInfo(): Cell does not exists");
960       return RFAILED;
961    }
962
963    GET_UE_IDX(dlBoInfo->crnti, ueId);
964    ueCb = &cell->ueCb[ueId-1];
965    lcId  = dlBoInfo->lcId;
966    CHECK_LCID(lcId, isLcIdValid);
967    if(isLcIdValid == FALSE)
968    {
969       DU_LOG("ERROR --> SCH: LCID:%d is not valid", lcId);
970       return RFAILED;
971    }
972
973    /*Expected when theres a case of Retransmission Failure or Resetablishment
974     *By Zero BO, the RLC is informing that previous data can be cleared out
975     *Thus clearing out the LC from the Lc priority list*/
976    if(dlBoInfo->dataVolume == 0)
977    {
978       /*Check the LC is Dedicated or default and accordingly LCList will
979        * be used*/
980       if(ueCb->dlInfo.dlLcCtxt[lcId].isDedicated)
981       {
982          lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
983       }
984       else
985       {
986          lcLL = &(ueCb->dlLcPrbEst.defLcList);
987       }
988       handleLcLList(lcLL, lcId, DELETE);
989       return ROK;
990    }
991
992    if(lcId == SRB0_LCID)
993    {
994       cell->raCb[ueId -1].msg4recvd = true;
995       cell->raCb[ueId -1].dlMsgPduLen = dlBoInfo->dataVolume;
996       
997    }
998    else
999    {
1000       /* TODO : These part of changes will be corrected during DL scheduling as
1001        * per K0 - K1 -K2 */
1002       SET_ONE_BIT(ueId, cell->boIndBitMap);
1003       if(ueCb->dlInfo.dlLcCtxt[lcId].lcId == lcId)
1004       {
1005          ueCb->dlInfo.dlLcCtxt[lcId].bo = dlBoInfo->dataVolume;
1006       }
1007       else
1008       {
1009          DU_LOG("ERROR --> SCH: LCID:%d is not configured in SCH Cb",lcId);
1010          return RFAILED;
1011       }
1012    }
1013    
1014    /* Adding UE Id to list of pending UEs to be scheduled */
1015    addUeToBeScheduled(cell, ueId);
1016    return ROK;
1017 }
1018
1019 /*******************************************************************
1020  *
1021  * @brief Processes BSR indiation from MAC
1022  *
1023  * @details
1024  *
1025  *    Function : MacSchBsr
1026  *
1027  *    Functionality:
1028  *       Processes DL BSR from MAC
1029  *
1030  * @params[in]    Pst pst
1031  *                UlBufferStatusRptInd bsrInd
1032  * @return ROK     - success
1033  *         RFAILED - failure
1034  *
1035  * ****************************************************************/
1036 uint8_t MacSchBsr(Pst *pst, UlBufferStatusRptInd *bsrInd)
1037 {
1038    Inst           schInst       = pst->dstInst-SCH_INST_START;
1039    SchCellCb      *cellCb       = NULLP;
1040    SchUeCb        *ueCb         = NULLP;
1041    uint8_t        lcgIdx = 0;
1042
1043 #ifdef CALL_FLOW_DEBUG_LOG
1044    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_SHORT_BSR\n");
1045 #endif
1046
1047    DU_LOG("\nDEBUG  -->  SCH : Received BSR");
1048    if(bsrInd == NULLP)
1049    {
1050       DU_LOG("\nERROR  -->  SCH : BSR Ind is empty");
1051       return RFAILED;
1052    }
1053    cellCb = schCb[schInst].cells[schInst];
1054    if(cellCb == NULLP)
1055    {
1056       DU_LOG("\nERROR  -->  SCH : CellCb is empty");
1057       return RFAILED;
1058    }
1059    ueCb = schGetUeCb(cellCb, bsrInd->crnti);
1060
1061    if(ueCb == NULLP)
1062    {
1063       DU_LOG("\nERROR  -->  SCH : UeCB is empty");
1064       return RFAILED;
1065    }
1066
1067    ueCb->bsrRcvd = true;
1068    /* store dataVolume per lcg in uecb */
1069    for(lcgIdx = 0; lcgIdx < bsrInd->numLcg; lcgIdx++)
1070    {
1071       ueCb->bsrInfo[bsrInd->dataVolInfo[lcgIdx].lcgId].priority = 1; //TODO: determining LCG priority?
1072       ueCb->bsrInfo[bsrInd->dataVolInfo[lcgIdx].lcgId].dataVol = bsrInd->dataVolInfo[lcgIdx].dataVol;
1073    }
1074    
1075    /* Adding UE Id to list of pending UEs to be scheduled */
1076    addUeToBeScheduled(cellCb, ueCb->ueIdx);
1077    return ROK;
1078 }
1079
1080 /*******************************************************************
1081  *
1082  * @brief Processes SR UCI indication from MAC 
1083  *
1084  * @details
1085  *
1086  *    Function : MacSchSrUciInd
1087  *
1088  *    Functionality:
1089  *      Processes SR UCI indication from MAC
1090  *
1091  * @params[in] Post structure
1092  *             UCI Indication
1093  * @return ROK     - success
1094  *         RFAILED - failure
1095  *
1096  * ****************************************************************/
1097 uint8_t MacSchSrUciInd(Pst *pst, SrUciIndInfo *uciInd)
1098 {
1099    Inst  inst = pst->dstInst-SCH_INST_START;
1100
1101    SchUeCb   *ueCb; 
1102    SchCellCb *cellCb = schCb[inst].cells[inst];
1103
1104 #ifdef CALL_FLOW_DEBUG_LOG
1105    DU_LOG("\nCall Flow: ENTMAC -> ENTSCH : EVENT_UCI_IND_TO_SCH\n");
1106 #endif
1107
1108    DU_LOG("\nDEBUG  -->  SCH : Received SR");
1109
1110    ueCb = schGetUeCb(cellCb, uciInd->crnti);
1111    
1112    if(ueCb->state == SCH_UE_STATE_INACTIVE)
1113    {
1114       DU_LOG("\nERROR  -->  SCH : Crnti %d is inactive", uciInd->crnti);
1115       return ROK;  
1116    }
1117
1118    if(uciInd->numSrBits)
1119    {
1120       ueCb->srRcvd = true;
1121       
1122       /* Adding UE Id to list of pending UEs to be scheduled */
1123       addUeToBeScheduled(cellCb, ueCb->ueIdx);
1124    }
1125    return ROK;
1126 }
1127
1128 /*******************************************************************
1129  *
1130  * @brief Allocates requested PRBs for DL
1131  *
1132  * @details
1133  *
1134  *    Function : allocatePrbDl
1135  *
1136  *    Functionality:
1137  *      Allocates requested PRBs in DL
1138  *      Keeps track of allocated PRB (using bitmap) and remaining PRBs
1139  *
1140  * @params[in] prbAlloc table
1141  *             Start symbol
1142  *             Number of symbols
1143  *             Start PRB
1144  *             Number of PRBs
1145  *
1146  * @return ROK     - success
1147  *         RFAILED - failure
1148  *
1149  * ****************************************************************/
1150 uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \
1151    uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
1152 {
1153    uint8_t        symbol = 0;
1154    uint16_t       broadcastPrbStart=0, broadcastPrbEnd=0;
1155    FreePrbBlock   *freePrbBlock = NULLP;
1156    CmLList        *freePrbNode = NULLP;
1157    PduTxOccsaion  ssbOccasion=0, sib1Occasion=0;
1158    SchDlSlotInfo  *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
1159    SchPrbAlloc    *prbAlloc = &schDlSlotInfo->prbAlloc;
1160
1161    /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
1162     * Search for an appropriate location in PRB grid and allocate requested resources */
1163    if(*startPrb == MAX_NUM_RB)
1164    {
1165       /* Check if SSB/SIB1 is also scheduled in this slot  */
1166       ssbOccasion = schCheckSsbOcc(cell, slotTime);
1167       sib1Occasion = schCheckSib1Occ(cell, slotTime);
1168
1169       if(ssbOccasion && sib1Occasion)
1170       {
1171          broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA; 
1172          broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1173       }
1174       else if(ssbOccasion)
1175       {
1176          broadcastPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1177          broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB -1;
1178       }
1179       else if(sib1Occasion)
1180       {
1181          broadcastPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
1182          broadcastPrbEnd = broadcastPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1183       }
1184
1185       /* Iterate through all free PRB blocks */
1186       freePrbNode = prbAlloc->freePrbBlockList.first; 
1187       while(freePrbNode)
1188       {
1189          freePrbBlock = (FreePrbBlock *)freePrbNode->node; 
1190
1191          /* If broadcast message is scheduled in this slot, then check if its PRBs belong to the current free block.
1192           * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
1193          if((ssbOccasion || sib1Occasion) && 
1194             ((broadcastPrbStart >= freePrbBlock->startPrb) && (broadcastPrbStart <= freePrbBlock->endPrb)) && \
1195             ((broadcastPrbEnd >= freePrbBlock->startPrb) && (broadcastPrbEnd <= freePrbBlock->endPrb)))
1196          {
1197             /* Implmentation is done such that highest-numbered free-RB is allocated first */ 
1198             if((freePrbBlock->endPrb > broadcastPrbEnd) && ((freePrbBlock->endPrb - broadcastPrbEnd) >= numPrb))
1199             {
1200                /* If sufficient free PRBs are available above bradcast message then,
1201                 * endPrb = freePrbBlock->endPrb
1202                 * startPrb = endPrb - numPrb +1;
1203                 */
1204                *startPrb = freePrbBlock->endPrb - numPrb +1;
1205                break;
1206             }
1207             else if((broadcastPrbStart > freePrbBlock->startPrb) && ((broadcastPrbStart - freePrbBlock->startPrb) >= numPrb))
1208             {
1209                /* If free PRBs are available below broadcast message then,
1210                 * endPrb = broadcastPrbStart - 1
1211                 * startPrb = endPrb - numPrb +1
1212                 */
1213                *startPrb = broadcastPrbStart - numPrb; 
1214                break;
1215             }
1216             else
1217             {
1218                freePrbNode = freePrbNode->next;
1219                continue;
1220             }
1221          }
1222          else
1223          {
1224             /* Check if requested number of blocks can be allocated from the current block */ 
1225             if (freePrbBlock->numFreePrb < numPrb)
1226             {
1227                freePrbNode = freePrbNode->next;
1228                continue;
1229             }
1230             *startPrb = freePrbBlock->endPrb - numPrb +1;
1231             break;  
1232          }
1233       }
1234
1235       /* If no free block can be used to allocated request number of RBs */
1236       if(*startPrb == MAX_NUM_RB)
1237          return RFAILED;
1238    }
1239
1240    /* If startPrb is known already, check if requested PRBs are available for allocation */
1241    else
1242    {
1243       freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1244       if(!freePrbNode)
1245       {
1246          DU_LOG("\nERROR  -->  SCH: Requested DL PRB unavailable");
1247          return RFAILED;
1248       }
1249    }
1250
1251    /* Update bitmap to allocate PRBs */
1252    for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1253    {
1254       if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1255       {
1256          DU_LOG("\nERROR  -->  SCH: fillPrbBitmap() failed for symbol [%d] in DL", symbol);
1257          return RFAILED;
1258       }
1259    }
1260
1261    /* Update the remaining number for free PRBs */
1262    removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1263
1264    return ROK;
1265 }
1266
1267 /*******************************************************************
1268  *
1269  * @brief Allocates requested PRBs for UL
1270  *
1271  * @details
1272  *
1273  *    Function : allocatePrbUl
1274  *
1275  *    Functionality:
1276  *      Allocates requested PRBs in UL
1277  *      Keeps track of allocated PRB (using bitmap) and remaining PRBs
1278  *
1279  * @params[in] prbAlloc table
1280  *             Start symbol
1281  *             Number of symbols
1282  *             Start PRB
1283  *             Number of PRBs
1284  *
1285  * @return ROK     - success
1286  *         RFAILED - failure
1287  *
1288  * ****************************************************************/
1289 uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \
1290    uint8_t startSymbol, uint8_t symbolLength, uint16_t *startPrb, uint16_t numPrb)
1291 {
1292    uint8_t        symbol = 0;
1293    uint16_t       prachStartPrb, prachNumPrb, prachEndPrb;
1294    bool           isPrachOccasion;
1295    FreePrbBlock   *freePrbBlock = NULLP;
1296    CmLList        *freePrbNode = NULLP;
1297    SchPrbAlloc    *prbAlloc = NULLP;
1298
1299    if(cell == NULLP)
1300    {
1301       DU_LOG("\nERROR  --> SCH : allocatePrbUl(): Received cellCb is null");
1302       return RFAILED;
1303    }
1304    
1305    prbAlloc =   &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
1306    /* If startPrb is set to MAX_NUM_RB, it means startPrb is not known currently.
1307     * Search for an appropriate location in PRB grid and allocate requested resources */
1308    if(*startPrb == MAX_NUM_RB)
1309    {
1310       /* Check if PRACH is also scheduled in this slot */
1311       isPrachOccasion = schCheckPrachOcc(cell, slotTime);
1312       if(isPrachOccasion)
1313       {
1314          prachStartPrb =  cell->cellCfg.schRachCfg.msg1FreqStart;
1315          prachNumPrb = schCalcPrachNumRb(cell);
1316          prachEndPrb = prachStartPrb + prachNumPrb -1;
1317       }
1318
1319       /* Iterate through all free PRB blocks */
1320       freePrbNode = prbAlloc->freePrbBlockList.first; 
1321       while(freePrbNode)
1322       {
1323          freePrbBlock = (FreePrbBlock *)freePrbNode->node; 
1324
1325          /* If PRACH is scheduled in this slot, then check if its PRBs belong to the current free block.
1326           * PRBs required for PRACH cannot be allocated to any other message */
1327          if((isPrachOccasion) &&
1328             ((prachStartPrb >= freePrbBlock->startPrb) && (prachStartPrb <= freePrbBlock->endPrb)) &&
1329             ((prachEndPrb >= freePrbBlock->startPrb) && (prachEndPrb <= freePrbBlock->endPrb)))
1330          {
1331             /* Implmentation is done such that highest-numbered free-RB is allocated first */ 
1332             if((freePrbBlock->endPrb > prachEndPrb) && ((freePrbBlock->endPrb - prachEndPrb) >= numPrb))
1333             {
1334                /* If sufficient free PRBs are available above PRACH message then,
1335                 * endPrb = freePrbBlock->endPrb
1336                 * startPrb = endPrb - numPrb +1;
1337                 */
1338                *startPrb = freePrbBlock->endPrb - numPrb +1;
1339                break;
1340             }
1341             else if((prachStartPrb > freePrbBlock->startPrb) && ((prachStartPrb - freePrbBlock->startPrb) >= numPrb))
1342             {
1343                /* If free PRBs are available below PRACH message then,
1344                 * endPrb = prachStartPrb - 1
1345                 * startPrb = endPrb - numPrb +1
1346                 */
1347                *startPrb = prachStartPrb - numPrb; 
1348                break;
1349             }
1350             else
1351             {
1352                freePrbNode = freePrbNode->next;
1353                continue;
1354             } 
1355          }
1356          else
1357          {
1358             /* Check if requested number of PRBs can be allocated from currect block */
1359             if(freePrbBlock->numFreePrb < numPrb)
1360             {
1361                freePrbNode = freePrbNode->next;
1362                continue;
1363             }
1364             *startPrb = freePrbBlock->endPrb - numPrb +1;
1365             break;
1366          }
1367       }
1368
1369       /* If no free block can be used to allocated requested number of RBs */
1370       if(*startPrb == MAX_NUM_RB)
1371          return RFAILED;
1372    }
1373    else
1374    {
1375       /* If startPrb is known already, check if requested PRBs are available for allocation */
1376       freePrbNode = isPrbAvailable(&prbAlloc->freePrbBlockList, *startPrb, numPrb);
1377       if(!freePrbNode)
1378       {
1379          DU_LOG("\nERROR  -->  SCH: Requested UL PRB unavailable");
1380          return RFAILED;
1381       }
1382    }
1383
1384    /* Update bitmap to allocate PRBs */
1385    for(symbol=startSymbol; symbol < (startSymbol+symbolLength); symbol++)
1386    {
1387       if(fillPrbBitmap(prbAlloc->prbBitMap[symbol], *startPrb, numPrb) != ROK)
1388       {
1389          DU_LOG("\nERROR  -->  SCH: fillPrbBitmap() failed for symbol [%d] in UL", symbol);
1390          return RFAILED;
1391       }
1392    }
1393
1394    /* Update the remaining number for free PRBs */
1395    removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb);
1396
1397    return ROK;
1398 }
1399
1400 /*******************************************************************
1401  *
1402  * @brief Add UE to ueToBeScheduled List
1403  *
1404  * @details
1405  *
1406  *    Function : addUeToBeScheduled
1407  *
1408  *    Functionality:
1409  *      Search if UE entry present in the list
1410  *      If yes, return.
1411  *      If no, add UE to the list
1412  *
1413  * @params[in] Cell control block
1414  *             Ue Idx to be added
1415  *
1416  * @return ROK     - success
1417  *         RFAILED - failure
1418  *
1419  * ****************************************************************/
1420 uint8_t addUeToBeScheduled(SchCellCb *cell, uint8_t ueIdToAdd)
1421 {
1422    uint8_t *ueId;
1423    CmLList *node;
1424
1425    /* Search if UE entry is already present in ueToBeScheduled list.
1426     * If yes, another entry for same UE not needed. Hence, return */
1427    node = cell->ueToBeScheduled.first;
1428    while(node)
1429    {
1430       ueId = (uint8_t *)node->node;
1431       if(*ueId == ueIdToAdd)
1432          return ROK;
1433       node = node->next;
1434    }
1435
1436    /* If UE entry not present already, add UE to the end of ueToBeScheduled list */
1437    SCH_ALLOC(ueId, sizeof(uint8_t));
1438    if(!ueId)
1439    {
1440       DU_LOG("\nERROR  -->  SCH : Memory allocation failure in addUeToBeScheduled");
1441       return RFAILED;
1442    }
1443    *ueId = ueIdToAdd;
1444    if(addNodeToLList(&cell->ueToBeScheduled, ueId, NULLP) != ROK)
1445    {
1446       DU_LOG("\nERROR  --> SCH : Failed to add UeIdx to cell->ueToBeScheduled list");
1447       return RFAILED;
1448    }
1449    return ROK;
1450 }
1451  
1452 /*******************************************************************************
1453  *
1454  * @brief Try to find Best Free Block with Max Num PRB 
1455  *
1456  * @details
1457  *
1458  *    Function : searchLargestFreeBlock
1459  *
1460  *    Functionality:
1461  *     Finds the FreeBlock with MaxNum of FREE PRB considering SSB/SIB1 ocassions.
1462  *
1463  * @params[in] I/P > prbAlloc table (FreeBlock list)
1464  *             I/P > Slot timing Info
1465  *             O/P > Start PRB
1466  *             I/P > Direction (UL/DL)
1467  *       
1468  *
1469  * @return Max Number of Free PRB 
1470  *         If 0, then no Suitable Free Block
1471  *
1472  * ********************************************************************************/
1473
1474 uint16_t searchLargestFreeBlock(SchCellCb *cell, SlotTimingInfo slotTime,uint16_t *startPrb, Direction dir)
1475 {
1476    uint16_t       reservedPrbStart=0, reservedPrbEnd=0, maxFreePRB = 0;
1477    FreePrbBlock   *freePrbBlock = NULLP;
1478    CmLList        *freePrbNode = NULLP;
1479    SchPrbAlloc    *prbAlloc = NULLP;
1480    bool           checkOccasion = FALSE;
1481
1482    *startPrb = 0; /*Initialize the StartPRB to zero*/
1483
1484    /*Based on Direction, Reserved Messsages will differi.e.
1485     * DL >> SSB and SIB1 ocassions wheres for UL, PRACH ocassions to be checked
1486     * and reserved before allocation for dedicated DL/UL msg*/
1487    if(dir == DIR_DL)
1488    {
1489       SchDlSlotInfo  *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
1490       PduTxOccsaion  ssbOccasion=0, sib1Occasion=0;
1491
1492       prbAlloc = &schDlSlotInfo->prbAlloc;
1493
1494       ssbOccasion = schCheckSsbOcc(cell, slotTime);
1495       sib1Occasion = schCheckSib1Occ(cell, slotTime);
1496
1497       checkOccasion = TRUE;
1498       if(ssbOccasion && sib1Occasion)
1499       {
1500          reservedPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA; 
1501          reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB + \
1502                           cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1503       }
1504       else if(ssbOccasion)
1505       {
1506          reservedPrbStart = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
1507          reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB -1;
1508       }
1509       else if(sib1Occasion)
1510       {
1511          reservedPrbStart = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.startPrb;
1512          reservedPrbEnd = reservedPrbStart + cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc.numPrb -1;
1513       }
1514       else
1515       {
1516          checkOccasion = FALSE;  
1517       }
1518    }
1519    else if(dir == DIR_UL)
1520    {
1521       prbAlloc = &cell->schUlSlotInfo[slotTime.slot]->prbAlloc;
1522
1523       /* Check if PRACH is also scheduled in this slot */
1524       checkOccasion = schCheckPrachOcc(cell, slotTime);
1525       if(checkOccasion)
1526       {
1527          reservedPrbStart =  cell->cellCfg.schRachCfg.msg1FreqStart;
1528          reservedPrbEnd = reservedPrbStart + (schCalcPrachNumRb(cell)) -1;
1529       }
1530    }
1531    else
1532    {
1533       DU_LOG("\nERROR --> SCH: Invalid Direction!");
1534       return (maxFreePRB);
1535    }
1536
1537    freePrbNode = prbAlloc->freePrbBlockList.first; 
1538    while(freePrbNode)
1539    {
1540       freePrbBlock = (FreePrbBlock *)freePrbNode->node;
1541
1542       /*For block with same numFreeBlocks, choose the one with HighestPRB range
1543        *Since FreeBLockList are arranged in Descending order of PRB range thus Skipping this block*/
1544       if(maxFreePRB >= freePrbBlock->numFreePrb) 
1545       {
1546          //skip this block
1547          freePrbNode = freePrbNode->next;
1548          continue;
1549       }
1550
1551       /* If Broadcast/Prach message is scheduled in this slot, then check if its PRBs belong to the current free block.
1552        * Since SSB/SIB1 PRB location is fixed, these PRBs cannot be allocated to other message in same slot */
1553       if(checkOccasion && 
1554             ((reservedPrbStart >= freePrbBlock->startPrb) && (reservedPrbStart <= freePrbBlock->endPrb)) && \
1555             ((reservedPrbEnd >= freePrbBlock->startPrb) && (reservedPrbEnd <= freePrbBlock->endPrb)))
1556       {
1557
1558          /* Implmentation is done such that highest-numbered free-RB is Checked first
1559             and freePRB in this block is greater than Max till now */
1560          if((freePrbBlock->endPrb > reservedPrbEnd) && ((freePrbBlock->endPrb - reservedPrbEnd) > maxFreePRB))
1561          {
1562             /* If sufficient free PRBs are available above reserved message*/
1563             *startPrb = reservedPrbEnd + 1;
1564             maxFreePRB = (freePrbBlock->endPrb - reservedPrbEnd);                
1565          }
1566          /*Also check the other freeBlock (i.e. Above the reserved message) for MAX FREE PRB*/
1567          if((reservedPrbStart > freePrbBlock->startPrb) && ((reservedPrbStart - freePrbBlock->startPrb) > maxFreePRB))
1568          {
1569             /* If free PRBs are available below reserved message*/
1570             *startPrb = freePrbBlock->startPrb;
1571             maxFreePRB = (reservedPrbStart - freePrbBlock->startPrb);
1572          }
1573       }
1574       else  //Best Block
1575       {
1576          if(maxFreePRB < freePrbBlock->numFreePrb)
1577          {
1578             *startPrb = freePrbBlock->startPrb;
1579             maxFreePRB = freePrbBlock->numFreePrb;
1580          }
1581
1582       }
1583       freePrbNode = freePrbNode->next;
1584    }  
1585    return(maxFreePRB);
1586 }
1587
1588 /*******************************************************************************
1589  *
1590  * @brief This function is used to send Slice Cfg rsp to MAC
1591  *
1592  * @details
1593  *
1594  *    Function : SchSendSliceCfgRspToMac
1595  *
1596  *    Functionality:
1597  *     function is used to send Slice Cfg rsp to MAC
1598  *
1599  * @params[in] Pst *pst, SchSliceCfgRsp sliceCfgRsp
1600  *
1601  * @return- void
1602  *
1603  * ********************************************************************************/
1604 void SchSendSliceCfgRspToMac(Inst inst, SchSliceCfgRsp sliceCfgRsp)
1605 {
1606    Pst rspPst;
1607    
1608    memset(&rspPst, 0, sizeof(Pst));
1609    FILL_PST_SCH_TO_MAC(rspPst, inst);
1610    rspPst.event = EVENT_SLICE_CFG_RSP_TO_MAC;
1611    
1612    SchSliceCfgRspOpts[rspPst.selector](&rspPst, &sliceCfgRsp);
1613
1614 }
1615 /*******************************************************************************
1616  *
1617  * @brief fill slice configuration response
1618  *
1619  * @details
1620  *
1621  *    Function : fillSliceCfgRsp
1622  *
1623  *    Functionality:
1624  *     fill slice configuration response
1625  *
1626  * @params[in] SchCellCb, SchSliceCfgReq, SchSliceCfgRsp,uint8_t  count
1627  *
1628  * @return
1629  *        ROK - Success
1630  *        RFAILED - Failure
1631  *
1632  * ********************************************************************************/
1633 uint8_t fillSliceCfgRsp(bool sliceReCfg, SchSliceCfg *storedSliceCfg, SchCellCb *cellCb, SchSliceCfgReq *schSliceCfgReq, SchSliceCfgRsp *schSliceCfgRsp, uint8_t *count)
1634 {
1635    bool sliceFound = false;
1636    uint8_t cfgIdx = 0, sliceIdx = 0;
1637
1638    schSliceCfgRsp->numSliceCfgRsp  = schSliceCfgReq->numOfConfiguredSlice;
1639    SCH_ALLOC(schSliceCfgRsp->listOfSliceCfgRsp, schSliceCfgRsp->numSliceCfgRsp * sizeof(SliceRsp*));
1640    if(schSliceCfgRsp->listOfSliceCfgRsp == NULLP)
1641    {
1642       DU_LOG("\nERROR  --> SCH : Memory allocation failed at fillSliceCfgRsp");
1643       return RFAILED;
1644    }
1645    
1646    for(cfgIdx = 0; cfgIdx<schSliceCfgRsp->numSliceCfgRsp ; cfgIdx++)
1647    {
1648       sliceFound = false;
1649       /* Here comparing the slice cfg request with the slice stored in cellCfg */
1650       if(sliceReCfg != true)
1651       {
1652          for(sliceIdx = 0; sliceIdx<cellCb->cellCfg.plmnInfoList.numSliceSupport; sliceIdx++)
1653          {
1654             if(!memcmp(&schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai, cellCb->cellCfg.plmnInfoList.snssai[sliceIdx], sizeof(Snssai)))
1655             {
1656                (*count)++;
1657                sliceFound = true;
1658                break;
1659             }
1660          }
1661       }
1662       else
1663       {
1664          /* Here comparing the slice cfg request with the slice stored in SchDb */
1665          if(storedSliceCfg->listOfConfirguration)
1666          {
1667             for(sliceIdx = 0; sliceIdx<storedSliceCfg->numOfSliceConfigured; sliceIdx++)
1668             {
1669                if(!memcmp(&schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai, &storedSliceCfg->listOfConfirguration[sliceIdx]->snssai,\
1670                         sizeof(Snssai)))
1671                {
1672                   (*count)++;
1673                   sliceFound = true;
1674                   break;
1675                }
1676             }
1677          }
1678       }
1679
1680       SCH_ALLOC(schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx], sizeof(SliceRsp));
1681       if(schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx] == NULLP)
1682       {
1683          DU_LOG("\nERROR  -->  SCH : Failed to allocate memory in fillSliceCfgRsp");
1684          return RFAILED;
1685       }
1686
1687       
1688       schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->snssai = schSliceCfgReq->listOfConfirguration[cfgIdx]->snssai;
1689       if(sliceFound == true)
1690          schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->rsp    = RSP_OK;
1691       else
1692       {
1693          schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->rsp    = RSP_NOK;
1694          schSliceCfgRsp->listOfSliceCfgRsp[cfgIdx]->cause  = SLICE_NOT_FOUND;
1695       }
1696    }
1697    return ROK;
1698 }
1699
1700 /*******************************************************************************
1701  *
1702  * @brief This function is used to store the slice configuration Sch DB
1703  *
1704  * @details
1705  *
1706  *    Function : addSliceCfgInSchDb 
1707  *
1708  *    Functionality:
1709  *     function is used to store the slice configuration Sch DB
1710  *
1711  * @params[in] SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq,
1712  * SchSliceCfgRsp cfgRsp, uint8_t count
1713  *
1714  * @return
1715  *        ROK - Success
1716  *        RFAILED - Failure
1717  *
1718  * ********************************************************************************/
1719 uint8_t addSliceCfgInSchDb(SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq, SchSliceCfgRsp cfgRsp, uint8_t count)
1720 {
1721    uint8_t cfgIdx = 0, sliceIdx = 0; 
1722    
1723    if(count)
1724    {
1725       storeSliceCfg->numOfSliceConfigured = count;
1726       SCH_ALLOC(storeSliceCfg->listOfConfirguration, storeSliceCfg->numOfSliceConfigured * sizeof(SchRrmPolicyOfSlice*));
1727       if(storeSliceCfg->listOfConfirguration == NULLP)
1728       {
1729          DU_LOG("\nERROR  -->  SCH : Failed to allocate memory in addSliceCfgInSchDb");
1730          return RFAILED;
1731       }
1732
1733       for(cfgIdx = 0; cfgIdx<storeSliceCfg->numOfSliceConfigured; cfgIdx++)
1734       {
1735          if(cfgRsp.listOfSliceCfgRsp[cfgIdx]->rsp == RSP_OK)
1736          {
1737             SCH_ALLOC(storeSliceCfg->listOfConfirguration[sliceIdx], sizeof(SchRrmPolicyOfSlice));
1738             if(storeSliceCfg->listOfConfirguration[sliceIdx] == NULLP)
1739             {
1740                DU_LOG("\nERROR  -->  SCH : Failed to allocate memory in addSliceCfgInSchDb");
1741                return RFAILED;
1742             }
1743
1744             SCH_ALLOC(storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));
1745             if(storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo == NULLP)
1746             {
1747                DU_LOG("\nERROR  -->  SCH : Failed to allocate memory in addSliceCfgInSchDb");
1748                return RFAILED;
1749             }
1750
1751             memcpy(storeSliceCfg->listOfConfirguration[sliceIdx], cfgReq->listOfConfirguration[sliceIdx], sizeof(SchRrmPolicyOfSlice));
1752             sliceIdx++;
1753          }
1754       }
1755    }
1756    return ROK;
1757 }
1758
1759 /*******************************************************************************
1760  *
1761  * @brief This function is used to free the slice cfg and re cfg request pointer
1762  *
1763  * @details
1764  *
1765  *    Function : freeSchSliceCfgReq 
1766  *
1767  *    Functionality:
1768  *     function is used to free the slice cfg and re cfg request pointer
1769  *
1770  * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1771  *
1772  * @return
1773  *        ROK - Success
1774  *        RFAILED - Failure
1775  * ********************************************************************************/
1776 void freeSchSliceCfgReq(SchSliceCfgReq *cfgReq)
1777 {
1778    uint8_t cfgIdx = 0;
1779    
1780    if(cfgReq)
1781    {
1782       if(cfgReq->numOfConfiguredSlice)
1783       {
1784          for(cfgIdx = 0; cfgIdx<cfgReq->numOfConfiguredSlice; cfgIdx++)
1785          {
1786             if(cfgReq->listOfConfirguration[cfgIdx])
1787             {
1788                SCH_FREE(cfgReq->listOfConfirguration[cfgIdx]->rrmPolicyRatioInfo, sizeof(SchRrmPolicyRatio));
1789                SCH_FREE(cfgReq->listOfConfirguration[cfgIdx], sizeof(SchRrmPolicyOfSlice));
1790             }
1791          }
1792          SCH_FREE(cfgReq->listOfConfirguration, cfgReq->numOfConfiguredSlice * sizeof(SchRrmPolicyOfSlice*));
1793       }
1794       SCH_FREE(cfgReq, sizeof(SchSliceCfgReq));
1795    }
1796 }
1797 /*******************************************************************************
1798  *
1799  * @brief This function is used to store the slice configuration Sch DB
1800  *
1801  * @details
1802  *
1803  *    Function : MacSchSliceCfgReq 
1804  *
1805  *    Functionality:
1806  *     function is used to store the slice configuration Sch DB
1807  *
1808  * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1809  *
1810  * @return
1811  *        ROK - Success
1812  *        RFAILED - Failure
1813  *
1814  * ********************************************************************************/
1815 uint8_t MacSchSliceCfgReq(Pst *pst, SchSliceCfgReq *schSliceCfgReq)
1816 {
1817    uint8_t count = 0;
1818    Inst   inst = pst->dstInst - 1;
1819    SchSliceCfgRsp sliceCfgRsp;
1820
1821    DU_LOG("\nINFO  -->  SCH : Received Slice Cfg request from MAC");
1822    if(schSliceCfgReq)
1823    {
1824       if(schSliceCfgReq->listOfConfirguration)
1825       {
1826          /* filling the slice configuration response of each slice */
1827          if(fillSliceCfgRsp(false, NULLP, schCb[inst].cells[0], schSliceCfgReq, &sliceCfgRsp, &count) != ROK)
1828          {
1829             DU_LOG("\nERROR  -->  SCH : Failed to fill the slice cfg rsp");
1830             return RFAILED;
1831          }
1832
1833          if(addSliceCfgInSchDb(&schCb[inst].sliceCfg, schSliceCfgReq, sliceCfgRsp, count) != ROK)
1834          {
1835             DU_LOG("\nERROR  -->  SCH : Failed to add slice cfg in sch database");
1836             return RFAILED;
1837          }
1838          freeSchSliceCfgReq(schSliceCfgReq);
1839          SchSendSliceCfgRspToMac(inst, sliceCfgRsp);
1840       }
1841    }
1842    else
1843    {
1844       DU_LOG("\nERROR  -->  SCH : Received SchSliceCfgReq is NULL");
1845    }
1846    return ROK;
1847 }
1848
1849 /*******************************************************************************
1850  *
1851  * @brief This function is used to store the slice reconfiguration Sch DB
1852  *
1853  * @details
1854  *
1855  *    Function : modifySliceCfgInSchDb 
1856  *
1857  *    Functionality:
1858  *     function is used to store the slice re configuration Sch DB
1859  *
1860  * @params[in] Pst *pst, SchSliceCfgReq *schSliceCfgReq
1861  *
1862  * @return
1863  *        ROK - Success
1864  *        RFAILED - Failure
1865  *
1866  * ********************************************************************************/
1867 uint8_t modifySliceCfgInSchDb(SchSliceCfg *storeSliceCfg, SchSliceCfgReq *cfgReq, SchSliceCfgRsp cfgRsp, uint8_t count)
1868 {
1869    uint8_t cfgIdx = 0, sliceIdx = 0; 
1870
1871    if(count)
1872    {
1873       if(storeSliceCfg->listOfConfirguration == NULLP)
1874       {
1875          DU_LOG("\nINFO  -->  SCH : Memory allocation failed in modifySliceCfgInSchDb");
1876          return RFAILED;
1877       }
1878
1879       for(cfgIdx = 0; cfgIdx<cfgReq->numOfConfiguredSlice; cfgIdx++)
1880       {
1881          if(cfgRsp.listOfSliceCfgRsp[cfgIdx]->rsp == RSP_OK)
1882          {
1883             for(sliceIdx = 0; sliceIdx<storeSliceCfg->numOfSliceConfigured; sliceIdx++)
1884             {
1885                if(!memcmp(&storeSliceCfg->listOfConfirguration[sliceIdx]->snssai, &cfgReq->listOfConfirguration[cfgIdx]->snssai, sizeof(Snssai)))
1886                {
1887                   storeSliceCfg->listOfConfirguration[sliceIdx]->rrmPolicyRatioInfo = cfgReq->listOfConfirguration[cfgIdx]->rrmPolicyRatioInfo;
1888                   break;
1889                }
1890             }
1891          }
1892       }
1893    }
1894    freeSchSliceCfgReq(cfgReq);
1895    return ROK;
1896 }
1897 /*******************************************************************************
1898  *
1899  * @brief This function is used to send Slice re Cfg rsp to MAC
1900  *
1901  * @details
1902  *
1903  *    Function : SchSendSliceCfgRspToMac
1904  *
1905  *    Functionality:
1906  *     function is used to send Slice re Cfg rsp to MAC
1907  *
1908  * @params[in] Pst *pst, SchSliceCfgRsp schSliceReCfgRsp
1909  *
1910  * @return- void
1911  *
1912  * ********************************************************************************/
1913 void SchSendSliceReCfgRspToMac(Inst inst, SchSliceCfgRsp schSliceReCfgRsp)
1914 {
1915    Pst rspPst;
1916    
1917    memset(&rspPst, 0, sizeof(Pst));
1918    FILL_PST_SCH_TO_MAC(rspPst, inst);
1919    rspPst.event = EVENT_SLICE_RECFG_RSP_TO_MAC;
1920    
1921    SchSliceReCfgRspOpts[rspPst.selector](&rspPst, &schSliceReCfgRsp);
1922 }
1923 /*******************************************************************************
1924  *
1925  * @brief This function is used to store the slice reconfiguration Sch DB
1926  *
1927  * @details
1928  *
1929  *    Function : MacSchSliceReCfgReq 
1930  *
1931  *    Functionality:
1932  *     function is used to store the slice re configuration Sch DB
1933  *
1934  * @params[in] Pst *pst, SchSliceCfgReq *schSliceReCfgReq
1935  *
1936  * @return
1937  *        ROK - Success
1938  *        RFAILED - Failure
1939  *
1940  * ********************************************************************************/
1941 uint8_t MacSchSliceReCfgReq(Pst *pst, SchSliceCfgReq *schSliceReCfgReq)
1942 {
1943    uint8_t count = 0;
1944    Inst   inst = pst->dstInst - 1;
1945    SchSliceCfgRsp schSliceReCfgRsp;
1946
1947    DU_LOG("\nINFO  -->  SCH : Received Slice ReCfg request from MAC");
1948    if(schSliceReCfgReq)
1949    {
1950       if(schSliceReCfgReq->listOfConfirguration)
1951       {
1952          /* filling the slice configuration response of each slice */
1953          if(fillSliceCfgRsp(true, &schCb[inst].sliceCfg, NULLP, schSliceReCfgReq, &schSliceReCfgRsp, &count) != ROK)
1954          {
1955             DU_LOG("\nERROR  -->  SCH : Failed to fill sch slice cfg response");
1956             return RFAILED;
1957          }
1958          
1959          /* Modify the slice configuration stored in schCb */
1960          if(modifySliceCfgInSchDb(&schCb[inst].sliceCfg, schSliceReCfgReq, schSliceReCfgRsp, count) != ROK)
1961          {
1962             DU_LOG("\nERROR  -->  SCH : Failed to modify slice cfg of SchDb");
1963             return RFAILED;
1964          }
1965          SchSendSliceReCfgRspToMac(inst, schSliceReCfgRsp);
1966       }
1967    }
1968    else
1969    {
1970       DU_LOG("\nERROR  -->  SCH : Received SchSliceCfgReq is NULL");
1971    }
1972    return ROK;
1973 }
1974
1975 /**********************************************************************
1976   End of file
1977  **********************************************************************/