JIRA ID: ODUHIGH-381 : DL packets Scheduling as per RRM Policy
[o-du/l2.git] / src / 5gnrsch / sch_slot_ind.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:     5G NR SCH layer
22
23 Type:     C source file
24
25 Desc:     C source code for Entry point fucntions for slot indications
26
27 File:     sch_slot_ind.c
28
29  **********************************************************************/
30
31 /** @file sch_slot_ind.c
32   @brief This module processes slot indications
33  */
34 #include "common_def.h"
35 #include "tfu.h"
36 #include "lrg.h"
37 #include "tfu.x"
38 #include "lrg.x"
39 #include "du_log.h"
40 #include "du_app_mac_inf.h"
41 #include "mac_sch_interface.h"
42 #include "sch.h"
43 #include "sch_utils.h"
44
45 SchMacDlAllocFunc schMacDlAllocOpts[] =
46 {
47    packSchMacDlAlloc,
48    MacProcDlAlloc,
49    packSchMacDlAlloc
50 };
51
52 /*******************************************************************
53  *
54  * @brief Handles sending DL broadcast alloc to MAC 
55  *
56  * @details
57  *
58  *    Function : sendDlAllocToMac
59  *
60  *    Functionality:
61  *     Sends DL Broadcast Resource Allocation to MAC from SCH
62  *
63  * @params[in] 
64  * @return ROK     - success
65  *         RFAILED - failure
66  *
67  * ****************************************************************/
68 uint8_t sendDlAllocToMac(DlSchedInfo *dlSchedInfo, Inst inst)
69 {
70    Pst pst;
71
72    memset(&pst, 0, sizeof(Pst));
73    FILL_PST_SCH_TO_MAC(pst, inst);
74    pst.event = EVENT_DL_SCH_INFO;
75
76    return(*schMacDlAllocOpts[pst.selector])(&pst, dlSchedInfo);
77
78 }
79
80 /*******************************************************************
81  *
82  * @brief Handles slot indication at SCH 
83  *
84  * @details
85  *
86  *    Function : schCalcSlotValues
87  *
88  *    Functionality:
89  *     Handles TTI indication received from PHY
90  *
91  * @params[in] 
92  * @return ROK     - success
93  *         RFAILED - failure
94  *
95  * ****************************************************************/
96 void schCalcSlotValues(SlotTimingInfo slotInd, SchSlotValue *schSlotValue)
97 {
98    /****************************************************************
99     * PHY_DELTA - the physical layer delta                         * 
100     * SCHED_DELTA - scheduler schedules one slot ahead             *
101     * BO_DELTA - this delay is considered for BO response and      *
102     *            RLC buffer packet to received at MAC              *
103     * lower-mac (FAPI filling) will be working on PHY_DELTA        *
104     * brdcast scheduler will working on PHY_DELTA + SCHED_DELTA    *
105     * RAR scheduler will working on PHY_DELTA + SCHED_DELTA        *
106     * msg4 scheduler will working on PHY_DELTA + SCHED_DELTA       *
107     * dedicated DL msg scheduler will working                      *
108     *        on PHY_DELTA + SCHED_DELTA + BO_DELTA                 *
109     ****************************************************************/
110
111    ADD_DELTA_TO_TIME(slotInd, schSlotValue->currentTime, PHY_DELTA_DL);
112    ADD_DELTA_TO_TIME(slotInd, schSlotValue->broadcastTime, PHY_DELTA_DL + SCHED_DELTA);
113    ADD_DELTA_TO_TIME(slotInd, schSlotValue->rarTime, PHY_DELTA_DL + SCHED_DELTA);
114    ADD_DELTA_TO_TIME(slotInd, schSlotValue->dlMsgTime, PHY_DELTA_DL + SCHED_DELTA);
115 }
116
117 /*******************************************************************
118  *
119  * @brief Checks if a slot is to be scheduled for SSB transmission
120  *
121  * @details
122  *
123  *    Function : schCheckSsbOcc 
124  *
125  *    Functionality:
126  *       Checks if a slot is to be scheduled for SSB transmission
127  *
128  * @params[in] SlotTimingInfo slotTime
129  *             SchCellCb *cell 
130  * @return  Pdu transmission 
131  *
132  * ****************************************************************/
133 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
134 {
135    uint8_t  ssb_rep;
136
137    ssb_rep = cell->cellCfg.ssbSchCfg.ssbPeriod;
138
139    /* Identify SSB ocassion*/
140    if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
141    {
142       return NEW_TRANSMISSION;
143    }
144    else if(cell->firstSsbTransmitted) 
145    {
146       if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
147          return REPEATITION;
148       else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
149          return REPEATITION;
150    }
151    /* not SSB occassion */
152    return NO_TRANSMISSION;
153 }
154
155 /*******************************************************************
156  *
157  * @brief Checks if a slot is to be scheduled for SIB1 transmission
158  *
159  * @details
160  *
161  *    Function : schCheckSib1Occ
162  *
163  *    Functionality:
164  *       Checks if a slot is to be scheduled for SIB1 transmission
165  *
166  * @params[in] SlotTimingInfo slotTime
167  *             SchCellCb *cell
168  * @return  Pdu transmission
169  *
170  * ****************************************************************/
171 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
172 {
173    /* Identify SIB1 occasions */
174    if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
175    {
176       return NEW_TRANSMISSION;
177    }
178    else if(cell->firstSib1Transmitted) 
179    {
180       if((slotTime.sfn % (cell->cellCfg.sib1SchCfg.sib1RepetitionPeriod/10) == 0) &&
181             (slotTime.slot == 0))
182       {
183          return REPEATITION;
184       }
185    }
186    /* not SIB1 occassion */
187    return NO_TRANSMISSION;
188 }
189
190 /*******************************************************************
191  *
192  * @brief 
193  *
194  * @details
195  *
196  *    Function : schFillBoGrantDlSchedInfo 
197  *
198  *    Functionality:
199  
200  *
201  * @params[in] 
202  * @return ROK     - success
203  *         RFAILED - failure
204  *
205  * ****************************************************************/
206 uint8_t schFillBoGrantDlSchedInfo(SchCellCb *cell, DlSchedInfo *dlSchedInfo, DlMsgAlloc *dlMsgAlloc)
207 {
208    uint8_t ueIdx = 0, lcIdx = 0, pdschSymbols = 0;
209    uint16_t slot = 0,  startPrb = 0, maxFreePRB = 0;
210    uint16_t crnti = 0, mcsIdx = 0;
211    uint32_t accumalatedSize = 0;
212    SchUeCb *ueCb = NULLP;
213    CmLListCp *lcLL = NULLP;
214    SchPdschConfig pdschCfg;
215
216    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
217     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
218     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
219     * else if only Default list is present then first node in this List will add this overhead len*/
220    bool isTxPayloadLenAdded = FALSE;
221
222    while(cell->boIndBitMap)
223    {
224       slot = dlSchedInfo->schSlotValue.dlMsgTime.slot;
225
226       GET_RIGHT_MOST_SET_BIT(cell->boIndBitMap, ueIdx);
227       GET_CRNTI(crnti,ueIdx);
228       ueCb = &cell->ueCb[ueIdx-1];
229
230       /* allocate PDCCH and PDSCH resources for the ue */
231       SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
232       if(!dlMsgAlloc)
233       {
234          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
235          return RFAILED;
236       }
237       memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
238       dlSchedInfo->dlMsgAlloc = dlMsgAlloc;
239       dlMsgAlloc->crnti = crnti;
240
241       pdschCfg = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg; 
242       mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
243
244       /*TODO: K0Index must be used instead of 0th Index in
245        * pdschCfg.timeDomRsrcAllociList*/
246       pdschSymbols = pdschCfg.timeDomRsrcAllociList[0].symbolLength;
247       /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
248       memcpy(&dlMsgAlloc->dlMsgInfo, cell->schDlSlotInfo[slot]->dlMsgInfo, \
249             sizeof(DlMsgInfo));
250
251       /*Re-Initalization per UE*/
252       /* scheduled LC data fill */
253       dlMsgAlloc->numLc = 0;
254       isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
255       accumalatedSize = 0;
256
257       for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
258       {
259          if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
260          {
261             /*Check the LC is Dedicated or default and accordingly LCList will
262              * be used*/
263             if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
264             {
265                lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
266             }
267             else
268             {
269                lcLL = &(ueCb->dlLcPrbEst.defLcList);
270             }
271
272             /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
273             if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
274                      (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
275             {
276                DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
277                /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
278                SCH_FREE(dlMsgAlloc, sizeof(DlMsgAlloc));
279                dlSchedInfo->dlMsgAlloc = NULLP;
280                return RFAILED;
281             }
282          }
283          ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
284       }//End of for loop
285
286
287       if ((ueCb->dlLcPrbEst.defLcList.count == 0) && \
288             ((ueCb->dlLcPrbEst.dedLcInfo != NULL) && (ueCb->dlLcPrbEst.dedLcInfo->dedLcList.count == 0)))
289       {
290          DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
291          /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
292          SCH_FREE(dlMsgAlloc, sizeof(DlMsgAlloc));
293          dlSchedInfo->dlMsgAlloc = NULLP;
294          return ROK;
295       }
296
297       /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
298       maxFreePRB = searchLargestFreeBlockDL(cell, dlSchedInfo->schSlotValue.dlMsgTime, &startPrb);
299
300       /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
301        * the list based on RRM policy*/
302
303       /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
304        * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
305       if(maxFreePRB != 0)
306       {
307          if((ueCb->dlLcPrbEst.dedLcInfo == NULLP) 
308                || ((maxFreePRB <  ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
309          { 
310             ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
311             DU_LOG("\nWARNING  --> SCH : Only Default Slice is scheduled, sharedPRB Count:%d",\
312                   ueCb->dlLcPrbEst.sharedNumPrb);
313
314             /*PRB Alloc for Default LCs*/
315             prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschSymbols,\
316                   &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded);
317          }
318          else
319          {
320             ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
321
322             /*PRB Alloc for Dedicated LCs*/
323             prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschSymbols,\
324                   &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
325
326             /*PRB Alloc for Default LCs*/
327             prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschSymbols, \
328                   &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
329          }
330       }
331
332       /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
333        * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
334       if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
335          updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dlMsgAlloc, &(accumalatedSize));
336
337       updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dlMsgAlloc, &(accumalatedSize));
338
339       /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
340       if (!accumalatedSize)
341       {
342          if(maxFreePRB == 0)
343          {
344             DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
345          }
346          else
347          {
348             /*Schedule the LC for next slot*/
349             DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
350          }
351          /*Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
352           * Allocation can be done in next slot*/
353          return ROK;
354       }
355       /*[Step6]: pdcch and pdsch data is filled */
356       if((schDlRsrcAllocDlMsg(cell, dlSchedInfo->schSlotValue.dlMsgTime, \
357                   crnti, accumalatedSize, dlMsgAlloc, startPrb)) != ROK)
358       {
359          DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
360          /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
361          SCH_FREE(dlMsgAlloc, sizeof(DlMsgAlloc));
362          dlSchedInfo->dlMsgAlloc = NULLP;
363          return RFAILED;
364       }
365
366       /* TODO : Update the scheduling byte report for multiple LC based on QCI
367        * and Priority */
368       /* As of now, the total number of bytes scheduled for a slot is divided
369        * equally amongst all LC with pending data. This is avoid starving of any
370        * LC 
371        * */
372 #if 0
373       accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
374       for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
375          dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
376 #endif
377       /* PUCCH resource */
378       schAllocPucchResource(cell, dlMsgAlloc->crnti, slot);
379
380       /* after allocation is done, unset the bo bit for that ue */
381       UNSET_ONE_BIT(ueIdx, cell->boIndBitMap);
382    }
383
384    return ROK;
385 }
386
387 /*******************************************************************
388  *
389  * @brief Handles slot indication at SCH 
390  *
391  * @details
392  *
393  *    Function : schProcessSlotInd
394  *
395  *    Functionality:
396  *     Handles TTI indication received from PHY
397  *
398  * @params[in] 
399  * @return ROK     - success
400  *         RFAILED - failure
401  *
402  * ****************************************************************/
403 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
404 {
405    uint8_t  ueIdx, lcgIdx, ret = ROK;
406    uint16_t slot;
407    DlSchedInfo dlSchedInfo;
408    DlBrdcstAlloc *dlBrdcstAlloc = NULLP;
409    DlMsgAlloc  *msg4Alloc = NULLP;
410    DlMsgAlloc *dlMsgAlloc = NULLP;
411    SchCellCb  *cell = NULLP;
412
413    memset(&dlSchedInfo,0,sizeof(DlSchedInfo));
414    dlSchedInfo.dlMsgAlloc = NULLP;
415    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue);
416    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
417    dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
418    dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
419
420    cell = schCb[schInst].cells[schInst];
421    if(cell == NULLP)
422    {
423       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
424       return RFAILED;
425    }
426    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
427    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
428
429    dlSchedInfo.cellId = cell->cellId;
430
431    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
432
433    /* Check for SSB occassion */
434    dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
435    if(dlBrdcstAlloc->ssbTrans)
436    {
437       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
438       {
439          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
440          dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
441       }
442       else 
443       {
444          dlSchedInfo.isBroadcastPres = true;
445          if((dlBrdcstAlloc->ssbTrans == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
446             cell->firstSsbTransmitted = true;
447       }
448    }
449
450    /* Check for SIB1 occassion */
451    dlBrdcstAlloc->sib1Trans = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
452    if(dlBrdcstAlloc->sib1Trans)
453    {
454       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
455       {
456          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
457          dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
458       }
459       else 
460       {
461          dlSchedInfo.isBroadcastPres = true;
462          if((dlBrdcstAlloc->sib1Trans == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
463             cell->firstSib1Transmitted = true;
464       }
465    }
466
467    /* Check for Pending RA Requests */
468    schProcessRaReq(*slotInd, cell);
469
470    /* Check for RAR */
471    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc != NULLP)
472    {
473       slot = dlSchedInfo.schSlotValue.rarTime.slot;
474       dlSchedInfo.rarAlloc = cell->schDlSlotInfo[slot]->rarAlloc;
475       cell->schDlSlotInfo[slot]->rarAlloc = NULLP;
476    }
477
478    /* Check for MSG4 */
479    if((cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo != NULLP) &&
480       (cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo->isMsg4Pdu))
481    {
482       slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
483
484       SCH_ALLOC(msg4Alloc, sizeof(DlMsgAlloc));
485       if(!msg4Alloc)
486       {
487          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for msg4 alloc");
488          return RFAILED;
489       }
490
491       dlSchedInfo.dlMsgAlloc = msg4Alloc;
492
493       /* Msg4 info is copied, this was earlier filled in macSchDlRlcBoInfo */
494       memcpy(&msg4Alloc->dlMsgInfo, cell->schDlSlotInfo[slot]->dlMsgInfo, \
495             sizeof(DlMsgInfo));
496
497       /* pdcch and pdsch data is filled */
498       if((schDlRsrcAllocMsg4(cell, dlSchedInfo.schSlotValue.dlMsgTime, msg4Alloc)) != ROK)
499       {
500          DU_LOG("\nERROR  -->  SCH : MSG4 scheduling failed");
501          SCH_FREE(msg4Alloc, sizeof(DlMsgAlloc));
502          dlSchedInfo.dlMsgAlloc = NULLP;
503          SCH_FREE(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo, sizeof(DlMsgInfo));
504          return RFAILED;
505       }
506
507       /* PUCCH resource */
508       schAllocPucchResource(cell, msg4Alloc->dlMsgInfo.crnti, dlSchedInfo.schSlotValue.dlMsgTime.slot);
509
510       SCH_FREE(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo, sizeof(DlMsgInfo));
511    }
512
513    /* Check if UL grant must be sent in this slot for a SR/BSR that had been received */
514    for(ueIdx=0; ueIdx<cell->numActvUe; ueIdx++)
515    {
516       uint32_t totDataReq = 0; /* in bytes */
517       DciInfo  *dciInfo = NULLP;
518       SchUeCb *ueCb = NULLP;
519    
520       ueCb = &cell->ueCb[ueIdx];
521       /* check for SR */
522       if(ueCb->srRcvd)
523       {
524          totDataReq = UL_GRANT_SIZE; /*fixing so that all control msgs can be handled in SR */
525          ueCb->srRcvd = false;
526       }
527       /* check for BSR */
528       for(lcgIdx=0; lcgIdx<MAX_NUM_LOGICAL_CHANNEL_GROUPS; lcgIdx++)
529       {
530         totDataReq+= ueCb->bsrInfo[lcgIdx].dataVol;
531         ueCb->bsrInfo[lcgIdx].dataVol = 0;
532       }
533       if(totDataReq > 0) /* UL grant must be provided for this UE in this slot */
534       {
535          SchPuschInfo schPuschInfo;
536          memset(&schPuschInfo, 0, sizeof(SchPuschInfo));
537
538          SCH_ALLOC(dciInfo, sizeof(DciInfo));
539          if(!dciInfo)
540          {
541             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciInfo alloc");
542             return RFAILED;
543          }
544          memset(dciInfo,0,sizeof(DciInfo));
545
546          /* update the SFN and SLOT */
547          memcpy(&dlSchedInfo.schSlotValue.ulDciTime, slotInd, sizeof(SlotTimingInfo));
548
549          /* Update PUSCH allocation */
550          schFillPuschAlloc(ueCb, dlSchedInfo.schSlotValue.ulDciTime, totDataReq, &schPuschInfo);
551
552          /* Fill DCI for UL grant */
553          schFillUlDci(ueCb, schPuschInfo, dciInfo);
554          memcpy(&dciInfo->slotIndInfo, &dlSchedInfo.schSlotValue.ulDciTime, sizeof(SlotTimingInfo));
555          dlSchedInfo.ulGrant = dciInfo;
556       }
557    }
558
559    /* Check for pending BO grant for LC */
560    if((cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo != NULLP) &&
561       (!cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo->isMsg4Pdu))
562    {
563       if((schFillBoGrantDlSchedInfo(cell, &dlSchedInfo, dlMsgAlloc)) != ROK)
564       {
565          DU_LOG("\nERROR  -->  SCH : DL MSG scheduling failed");
566          SCH_FREE(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo, sizeof(DlMsgInfo));
567          return RFAILED;
568       }
569
570       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
571       SCH_FREE(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgInfo, sizeof(DlMsgInfo));
572    }
573
574    /* Send msg to MAC */
575    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
576    if(ret != ROK)
577    {
578       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
579       return (ret);
580    }
581
582    schInitDlSlot(cell->schDlSlotInfo[slot]);
583    schUlResAlloc(cell, schInst);
584
585    return ret;
586 }
587
588 /**********************************************************************
589   End of file
590  **********************************************************************/
591
592