Changes for Multi-UE support and DL_MSG scheduling using K0 and K1 [Issue-ID: ODUHIGH...
[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 find correct combination of k0-k1 value
193  *
194  * @details
195  *
196  *    Function : findValidK0K1Value
197  *
198  *    Functionality:
199  *       find correct combination of k0-k1 value
200  *
201  * @params[in]
202  * @return ROK     - success
203  *         RFAILED - failure
204  *
205  *******************************************************************/
206 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg, uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,  SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime)
207 {
208    uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
209    uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
210    SchUeCb *ueCb = NULLP;
211    SchK0K1TimingInfoTbl *k0K1InfoTbl;
212
213    ADD_DELTA_TO_TIME(currTime, (*pdcchTime), PHY_DELTA_DL + SCHED_DELTA);
214 #ifdef NR_TDD
215    if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
216    {
217       /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
218       return false;
219    }
220 #endif
221
222    if(cell->schDlSlotInfo[pdcchTime->slot]->pdcchUe != 0)
223    {
224       return false;
225    }
226
227    if(dedMsg == true)
228    {
229       ueCb = &cell->ueCb[ueId-1];
230       k0K1InfoTbl = &ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1InfoTbl;
231    }
232    else
233    {
234       k0K1InfoTbl = &cell->cellCfg.schInitialDlBwp.k0K1InfoTbl;
235    }
236
237    numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
238    for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
239    {
240       k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
241       if(dedMsg != true)
242       {
243          k0Val = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
244          *pdschStartSymbol = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
245          *pdschSymblLen = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
246       }
247       else
248       {
249          if(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
250          {
251             k0Val = *(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
252             *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
253             *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
254          }
255       }
256
257       ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val);
258 #ifdef NR_TDD
259       if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
260       {
261          continue;
262       }
263 #endif
264       if(cell->schDlSlotInfo[pdschTime->slot]->pdschUe != 0)
265       {
266          continue; 
267       }
268
269       numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
270       for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
271       {
272          k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
273          if(dedMsg != true)
274          {
275             k1Val = defaultUlAckTbl[k1Index];
276          }
277          else
278          {
279             if(ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck)
280             {
281                k1Val = ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
282             }
283          }
284          ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val);
285 #ifdef NR_TDD
286          if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
287          {
288             continue;
289          }
290 #endif
291          if(cell->schUlSlotInfo[pucchTime->slot]->pucchUe != 0)
292          {
293             continue; 
294          }
295          return true;
296       }
297    }
298    return false;
299 }
300
301 /*******************************************************************
302  *
303  * @brief 
304  *
305  * @details
306  *
307  *    Function : schFillBoGrantDlSchedInfo 
308  *
309  *    Functionality:
310  
311  *
312  * @params[in] 
313  * @return ROK     - success
314  *         RFAILED - failure
315  *
316  * ****************************************************************/
317 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId)
318 {
319    uint8_t lcIdx = 0;
320    uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
321    uint16_t startPrb = 0, maxFreePRB = 0;
322    uint16_t crnti = 0, mcsIdx = 0;
323    uint32_t accumalatedSize = 0;
324    SchUeCb *ueCb = NULLP;
325    CmLListCp *lcLL = NULLP;
326    DlMsgAlloc *dciSlotAlloc, *dlMsgAlloc;
327    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
328
329    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
330     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
331     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
332     * else if only Default list is present then first node in this List will add this overhead len*/
333    bool isTxPayloadLenAdded = FALSE;
334
335    GET_CRNTI(crnti,ueId);
336    ueCb = &cell->ueCb[ueId-1];
337
338    if(findValidK0K1Value(cell, currTime, ueId, ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1TblPrsnt,\
339             &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, &pucchTime) != true )
340    {
341       /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
342        * not found, do not perform resource allocation. Return from here. */
343       return false;
344    }
345
346    /* allocate PDCCH and PDSCH resources for the ue */
347    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
348    {
349
350       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgAlloc));
351       if(!dciSlotAlloc)
352       {
353          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
354          return false;
355       }
356       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
357       memset(dciSlotAlloc, 0, sizeof(DlMsgAlloc));
358       dciSlotAlloc->crnti = crnti;
359    }
360    dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
361
362    /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
363    fillDlMsgInfo(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].dlMsgInfo, dciSlotAlloc->crnti);
364
365    /*Re-Initalization per UE*/
366    /* scheduled LC data fill */
367    dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].numLc = 0;
368    isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
369    accumalatedSize = 0;
370
371    for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
372    {
373       if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
374       {
375          /*Check the LC is Dedicated or default and accordingly LCList will
376           * be used*/
377          if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
378          {
379             lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
380          }
381          else
382          {
383             lcLL = &(ueCb->dlLcPrbEst.defLcList);
384          }
385
386          /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
387          if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
388                   (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
389          {
390             DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
391             /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
392             if(dciSlotAlloc->numSchedInfo == 0)
393             {
394                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
395                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
396             }
397             else
398                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
399             return false;
400          }
401       }
402       ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
403    }//End of for loop
404
405
406    if ((ueCb->dlLcPrbEst.defLcList.count == 0) && \
407          ((ueCb->dlLcPrbEst.dedLcInfo != NULL) && (ueCb->dlLcPrbEst.dedLcInfo->dedLcList.count == 0)))
408    {
409       DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
410       if(*(uint8_t *)cell->ueToBeScheduled.first->node == ueId)
411       {
412          SCH_FREE(cell->ueToBeScheduled.first->node, sizeof(uint8_t));
413          deleteNodeFromLList(&cell->ueToBeScheduled, cell->ueToBeScheduled.first);
414       }
415       UNSET_ONE_BIT(ueId, cell->boIndBitMap);
416
417       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
418       if(dciSlotAlloc->numSchedInfo == 0)
419       {
420          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
421          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
422       }
423       else
424          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
425       return false;
426    }
427
428    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
429    maxFreePRB = searchLargestFreeBlockDL(cell, pdschTime, &startPrb);
430
431    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
432     * the list based on RRM policy*/
433
434    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
435     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
436    if(maxFreePRB != 0)
437    {
438       mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
439       if((ueCb->dlLcPrbEst.dedLcInfo == NULLP) 
440             || ((maxFreePRB <  ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
441       { 
442          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
443          DU_LOG("\nWARNING  --> SCH : Only Default Slice is scheduled, sharedPRB Count:%d",\
444                ueCb->dlLcPrbEst.sharedNumPrb);
445
446          /*PRB Alloc for Default LCs*/
447          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
448                &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded);
449       }
450       else
451       {
452          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
453
454          /*PRB Alloc for Dedicated LCs*/
455          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
456                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
457
458          /*PRB Alloc for Default LCs*/
459          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
460                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
461       }
462    }
463
464    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
465     * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
466    if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
467       updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dciSlotAlloc, &(accumalatedSize));
468
469    updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dciSlotAlloc, &(accumalatedSize));
470
471    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
472    if (!accumalatedSize)
473    {
474       if(maxFreePRB == 0)
475       {
476          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
477       }
478       else
479       {
480          /*Schedule the LC for next slot*/
481          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
482       }
483       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
484        * Allocation can be done in next slot*/
485       return false;
486    }
487
488    /*[Step6]: pdcch and pdsch data is filled */
489    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb, pdschStartSymbol, pdschNumSymbols)) != ROK)
490    {
491       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
492
493       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
494       if(dciSlotAlloc->numSchedInfo == 0)
495       {
496          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
497          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
498       }
499       else
500          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
501       return false;
502    }
503
504    /* TODO : Update the scheduling byte report for multiple LC based on QCI
505     * and Priority */
506    /* As of now, the total number of bytes scheduled for a slot is divided
507     * equally amongst all LC with pending data. This is avoid starving of any
508     * LC 
509     * */
510 #if 0
511    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
512    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
513       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
514 #endif
515    
516    /* Check if both DCI and DL_MSG are sent in the same slot.
517     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
518
519    if(pdcchTime.slot == pdschTime.slot)
520    {
521       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = BOTH;
522       dciSlotAlloc->numSchedInfo++;
523    }
524    else
525    {
526       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
527       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
528       {
529          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
530          if(dlMsgAlloc == NULLP)
531          {
532             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
533             if(dciSlotAlloc->numSchedInfo == 0)
534             {
535                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
536                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
537             }
538             else
539                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
540             return false;
541          }
542          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
543          memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
544          dlMsgAlloc->crnti = dciSlotAlloc->crnti;
545       }
546       else
547          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
548
549       /* Copy all DL_MSG info */
550       memcpy(&dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo], \
551             &dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], sizeof(DlMsgSchInfo));
552       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdcchCfg.dci.pdschCfg = \
553             &dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdschCfg;
554
555       /* Assign correct PDU types in corresponding slots */
556       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].pduPres = PDSCH_PDU;
557       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = PDCCH_PDU;
558       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pdschSlot = pdschTime.slot;
559
560       dciSlotAlloc->numSchedInfo++;
561       dlMsgAlloc->numSchedInfo++;
562    }
563
564    schAllocPucchResource(cell, pucchTime, crnti);
565    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
566    cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
567    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
568
569    /* after allocation is done, unset the bo bit for that ue */
570    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
571  
572    return true;
573 }
574
575 /*******************************************************************
576  *
577  * @brief Handles slot indication at SCH 
578  *
579  * @details
580  *
581  *    Function : schProcessSlotInd
582  *
583  *    Functionality:
584  *     Handles TTI indication received from PHY
585  *
586  * @params[in] 
587  * @return ROK     - success
588  *         RFAILED - failure
589  *
590  * ****************************************************************/
591 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
592 {
593    uint8_t   ueId, ueIdx, lcgIdx, ret = ROK;
594    uint16_t  slot;
595    bool      isRarPending = false, isRarScheduled = false;
596    bool      isMsg4Pending = false, isMsg4Scheduled = false;
597    CmLList       *pendingUeNode;
598    DlSchedInfo   dlSchedInfo;
599    DlBrdcstAlloc *dlBrdcstAlloc = NULLP;
600    SchCellCb     *cell = NULLP;
601
602    memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
603    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue);
604    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
605    dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
606    dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
607
608    cell = schCb[schInst].cells[schInst];
609    if(cell == NULLP)
610    {
611       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
612       return RFAILED;
613    }
614    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
615    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
616
617    dlSchedInfo.cellId = cell->cellId;
618    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
619
620    /* Check for SSB occassion */
621    dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
622    if(dlBrdcstAlloc->ssbTrans)
623    {
624       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
625       {
626          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
627          dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
628       }
629       else 
630       {
631          dlSchedInfo.isBroadcastPres = true;
632          if((dlBrdcstAlloc->ssbTrans == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
633             cell->firstSsbTransmitted = true;
634       }
635    }
636
637    /* Check for SIB1 occassion */
638    dlBrdcstAlloc->sib1Trans = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
639    if(dlBrdcstAlloc->sib1Trans)
640    {
641       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
642       {
643          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
644          dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
645       }
646       else 
647       {
648          dlSchedInfo.isBroadcastPres = true;
649          if((dlBrdcstAlloc->sib1Trans == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
650             cell->firstSib1Transmitted = true;
651       }
652    }
653
654    /* Select first UE in the linked list to be scheduled next */
655    pendingUeNode = cell->ueToBeScheduled.first;
656    if(pendingUeNode)
657    {
658       ueId = *(uint8_t *)(pendingUeNode->node);
659
660       /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
661        * PUSCH to receive MSG3 as per k0-k2 configuration*/
662       if(cell->raReq[ueId-1] != NULLP)
663       {
664          isRarPending = true;
665          isRarScheduled = schProcessRaReq(cell, *slotInd, ueId);
666       }
667
668       /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
669        * PUCCH to receive UL msg as per k0-k1 configuration  */
670       if(cell->raCb[ueId-1].msg4recvd)
671       {
672          isMsg4Pending = true;
673          isMsg4Scheduled = schProcessMsg4Req(cell, *slotInd, ueId);
674       }
675
676       if(isRarPending || isMsg4Pending)
677       {
678          /* If RAR or MSG is successfully scheduled then
679           * remove UE from linked list since no pending msgs for this UE */
680          if(isRarScheduled || isMsg4Scheduled)
681          {
682             SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
683             deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
684          }
685          /* If RAR/MSG4 is pending but couldnt be scheduled then,
686           * put this UE at the end of linked list to be scheduled later */
687          else 
688          {
689             cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
690          }
691       }
692       
693       if((cell->boIndBitMap) & (1<<ueId))
694       {
695           if(schFillBoGrantDlSchedInfo(cell, *slotInd, ueId) == true)
696           {
697              SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
698              deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
699           }
700       }
701    }
702
703    /* Check if any PDU is scheduled at this slot for any UE */
704    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
705    {
706       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
707        * structure to send to MAC */
708       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
709       {
710          slot = dlSchedInfo.schSlotValue.rarTime.slot;
711          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
712          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
713       }
714    
715       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
716        * specific interface structure to send to MAC */
717       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
718       {
719          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
720          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
721          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
722       }
723
724    }
725
726    /* Check if UL grant must be sent in this slot for a SR/BSR that had been received */
727    for(ueIdx=0; ueIdx<cell->numActvUe; ueIdx++)
728    {
729       uint32_t totDataReq = 0; /* in bytes */
730       DciInfo  *dciInfo = NULLP;
731       SchUeCb *ueCb = NULLP;
732    
733       ueCb = &cell->ueCb[ueIdx];
734       /* check for SR */
735       if(ueCb->srRcvd)
736       {
737          totDataReq = UL_GRANT_SIZE; /*fixing so that all control msgs can be handled in SR */
738          ueCb->srRcvd = false;
739       }
740       /* check for BSR */
741       for(lcgIdx=0; lcgIdx<MAX_NUM_LOGICAL_CHANNEL_GROUPS; lcgIdx++)
742       {
743         totDataReq+= ueCb->bsrInfo[lcgIdx].dataVol;
744         ueCb->bsrInfo[lcgIdx].dataVol = 0;
745       }
746       if(totDataReq > 0) /* UL grant must be provided for this UE in this slot */
747       {
748          SchPuschInfo schPuschInfo;
749          memset(&schPuschInfo, 0, sizeof(SchPuschInfo));
750
751          SCH_ALLOC(dciInfo, sizeof(DciInfo));
752          if(!dciInfo)
753          {
754             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciInfo alloc");
755             return RFAILED;
756          }
757          memset(dciInfo,0,sizeof(DciInfo));
758
759          /* update the SFN and SLOT */
760          memcpy(&dlSchedInfo.schSlotValue.ulDciTime, slotInd, sizeof(SlotTimingInfo));
761
762          /* Update PUSCH allocation */
763          schFillPuschAlloc(ueCb, dlSchedInfo.schSlotValue.ulDciTime, totDataReq, &schPuschInfo);
764
765          /* Fill DCI for UL grant */
766          schFillUlDci(ueCb, schPuschInfo, dciInfo);
767          memcpy(&dciInfo->slotIndInfo, &dlSchedInfo.schSlotValue.ulDciTime, sizeof(SlotTimingInfo));
768          dlSchedInfo.ulGrant = dciInfo;
769       }
770    }
771
772    /* Send msg to MAC */
773    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
774    if(ret != ROK)
775    {
776       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
777       return (ret);
778    }
779
780    schInitDlSlot(cell->schDlSlotInfo[slot]);
781    schUlResAlloc(cell, schInst);
782
783    return ret;
784 }
785
786 /**********************************************************************
787   End of file
788  **********************************************************************/
789
790