b0a5bbd73439b8d6ec78c935bacd97e2292900a2
[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    ADD_DELTA_TO_TIME(slotInd, schSlotValue->ulDciTime, PHY_DELTA_DL + SCHED_DELTA);
116 }
117
118 /*******************************************************************
119  *
120  * @brief Checks if a slot is to be scheduled for SSB transmission
121  *
122  * @details
123  *
124  *    Function : schCheckSsbOcc 
125  *
126  *    Functionality:
127  *       Checks if a slot is to be scheduled for SSB transmission
128  *
129  * @params[in] SlotTimingInfo slotTime
130  *             SchCellCb *cell 
131  * @return  Pdu transmission 
132  *
133  * ****************************************************************/
134 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
135 {
136    uint8_t  ssb_rep;
137
138    ssb_rep = cell->cellCfg.ssbSchCfg.ssbPeriod;
139
140    /* Identify SSB ocassion*/
141    if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
142    {
143       return NEW_TRANSMISSION;
144    }
145    else if(cell->firstSsbTransmitted) 
146    {
147       if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
148          return REPEATITION;
149       else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
150          return REPEATITION;
151    }
152    /* not SSB occassion */
153    return NO_TRANSMISSION;
154 }
155
156 /*******************************************************************
157  *
158  * @brief Checks if a slot is to be scheduled for SIB1 transmission
159  *
160  * @details
161  *
162  *    Function : schCheckSib1Occ
163  *
164  *    Functionality:
165  *       Checks if a slot is to be scheduled for SIB1 transmission
166  *
167  * @params[in] SlotTimingInfo slotTime
168  *             SchCellCb *cell
169  * @return  Pdu transmission
170  *
171  * ****************************************************************/
172 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
173 {
174    /* Identify SIB1 occasions */
175    if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
176    {
177       return NEW_TRANSMISSION;
178    }
179    else if(cell->firstSib1Transmitted) 
180    {
181       if((slotTime.sfn % (cell->cellCfg.sib1SchCfg.sib1RepetitionPeriod/10) == 0) &&
182             (slotTime.slot == 0))
183       {
184          return REPEATITION;
185       }
186    }
187    /* not SIB1 occassion */
188    return NO_TRANSMISSION;
189 }
190
191 /*******************************************************************
192  *
193  * @brief find correct combination of k0-k1 value
194  *
195  * @details
196  *
197  *    Function : findValidK0K1Value
198  *
199  *    Functionality:
200  *       find correct combination of k0-k1 value
201  *
202  * @params[in]
203  * @return ROK     - success
204  *         RFAILED - failure
205  *
206  *******************************************************************/
207 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg, uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,  SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime)
208 {
209    uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
210    uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
211    SchUeCb *ueCb = NULLP;
212    SchK0K1TimingInfoTbl *k0K1InfoTbl;
213
214    ADD_DELTA_TO_TIME(currTime, (*pdcchTime), PHY_DELTA_DL + SCHED_DELTA);
215 #ifdef NR_TDD
216    if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
217    {
218       /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
219       return false;
220    }
221 #endif
222
223    if(cell->schDlSlotInfo[pdcchTime->slot]->pdcchUe != 0)
224    {
225       return false;
226    }
227
228    if(dedMsg == true)
229    {
230       ueCb = &cell->ueCb[ueId-1];
231       k0K1InfoTbl = &ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1InfoTbl;
232    }
233    else
234    {
235       k0K1InfoTbl = &cell->cellCfg.schInitialDlBwp.k0K1InfoTbl;
236    }
237
238    numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
239    for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
240    {
241       k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
242       if(dedMsg != true)
243       {
244          k0Val = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
245          *pdschStartSymbol = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
246          *pdschSymblLen = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
247       }
248       else
249       {
250          if(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
251          {
252             k0Val = *(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
253             *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
254             *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
255          }
256       }
257
258       ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val);
259 #ifdef NR_TDD
260       if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
261       {
262          continue;
263       }
264 #endif
265       if(cell->schDlSlotInfo[pdschTime->slot]->pdschUe != 0)
266       {
267          continue; 
268       }
269
270       numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
271       for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
272       {
273          k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
274          if(dedMsg != true)
275          {
276             k1Val = defaultUlAckTbl[k1Index];
277          }
278          else
279          {
280             if(ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck)
281             {
282                k1Val = ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
283             }
284          }
285          ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val);
286 #ifdef NR_TDD
287          if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
288          {
289             continue;
290          }
291 #endif
292          if(cell->schUlSlotInfo[pucchTime->slot]->pucchUe != 0)
293          {
294             continue; 
295          }
296          return true;
297       }
298    }
299    return false;
300 }
301
302 /*******************************************************************
303  *
304  * @brief 
305  *
306  * @details
307  *
308  *    Function : schFillBoGrantDlSchedInfo 
309  *
310  *    Functionality:
311  
312  *
313  * @params[in] 
314  * @return ROK     - success
315  *         RFAILED - failure
316  *
317  * ****************************************************************/
318 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId)
319 {
320    uint8_t lcIdx = 0;
321    uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
322    uint16_t startPrb = 0, maxFreePRB = 0;
323    uint16_t crnti = 0, mcsIdx = 0;
324    uint32_t accumalatedSize = 0;
325    SchUeCb *ueCb = NULLP;
326    CmLListCp *lcLL = NULLP;
327    DlMsgAlloc *dciSlotAlloc, *dlMsgAlloc;
328    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
329
330    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
331     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
332     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
333     * else if only Default list is present then first node in this List will add this overhead len*/
334    bool isTxPayloadLenAdded = FALSE;
335
336    GET_CRNTI(crnti,ueId);
337    ueCb = &cell->ueCb[ueId-1];
338
339    if(findValidK0K1Value(cell, currTime, ueId, ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1TblPrsnt,\
340             &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, &pucchTime) != true )
341    {
342       /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
343        * not found, do not perform resource allocation. Return from here. */
344       return false;
345    }
346
347    /* allocate PDCCH and PDSCH resources for the ue */
348    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
349    {
350
351       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgAlloc));
352       if(!dciSlotAlloc)
353       {
354          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
355          return false;
356       }
357       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
358       memset(dciSlotAlloc, 0, sizeof(DlMsgAlloc));
359       dciSlotAlloc->crnti = crnti;
360    }
361    dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
362
363    /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
364    fillDlMsgInfo(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].dlMsgInfo, dciSlotAlloc->crnti);
365
366    /*Re-Initalization per UE*/
367    /* scheduled LC data fill */
368    dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].numLc = 0;
369    isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
370    accumalatedSize = 0;
371
372    for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
373    {
374       if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
375       {
376          /*Check the LC is Dedicated or default and accordingly LCList will
377           * be used*/
378          if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
379          {
380             lcLL = &(ueCb->dlLcPrbEst.dedLcInfo->dedLcList);
381          }
382          else
383          {
384             lcLL = &(ueCb->dlLcPrbEst.defLcList);
385          }
386
387          /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
388          if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
389                   (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
390          {
391             DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
392             /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
393             if(dciSlotAlloc->numSchedInfo == 0)
394             {
395                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
396                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
397             }
398             else
399                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
400             return false;
401          }
402       }
403       ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
404    }//End of for loop
405
406
407    if ((ueCb->dlLcPrbEst.defLcList.count == 0) && \
408          ((ueCb->dlLcPrbEst.dedLcInfo == NULL) || (ueCb->dlLcPrbEst.dedLcInfo->dedLcList.count == 0)))
409    {
410       DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
411       UNSET_ONE_BIT(ueId, cell->boIndBitMap);
412
413       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
414       if(dciSlotAlloc->numSchedInfo == 0)
415       {
416          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
417          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
418       }
419       else
420          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
421
422       /*TRUE because this UE has nothing to be scheduled*/
423       return true;
424    }
425
426    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
427    maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
428
429    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
430     * the list based on RRM policy*/
431
432    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
433     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
434    if(maxFreePRB != 0)
435    {
436       mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
437       if((ueCb->dlLcPrbEst.dedLcInfo == NULLP) 
438             || ((maxFreePRB <  ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
439       { 
440          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
441          DU_LOG("\nDEBUG  --> SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
442                ueCb->dlLcPrbEst.sharedNumPrb);
443
444          /*PRB Alloc for Default LCs*/
445          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
446                &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
447       }
448       else
449       {
450          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
451
452          /*PRB Alloc for Dedicated LCs*/
453          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
454                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
455
456          /*PRB Alloc for Default LCs*/
457          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
458                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
459       }
460    }
461
462    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
463     * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
464    if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
465       updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
466
467    updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
468
469    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
470    if (!accumalatedSize)
471    {
472       if(maxFreePRB == 0)
473       {
474          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
475       }
476       else
477       {
478          /*Schedule the LC for next slot*/
479          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
480       }
481       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
482        * Allocation can be done in next slot*/
483       return false;
484    }
485
486    /*[Step6]: pdcch and pdsch data is filled */
487    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb, pdschStartSymbol, pdschNumSymbols)) != ROK)
488    {
489       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
490
491       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
492       if(dciSlotAlloc->numSchedInfo == 0)
493       {
494          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
495          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
496       }
497       else
498          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
499       return false;
500    }
501
502    /* TODO : Update the scheduling byte report for multiple LC based on QCI
503     * and Priority */
504    /* As of now, the total number of bytes scheduled for a slot is divided
505     * equally amongst all LC with pending data. This is avoid starving of any
506     * LC 
507     * */
508 #if 0
509    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
510    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
511       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
512 #endif
513    
514    /* Check if both DCI and DL_MSG are sent in the same slot.
515     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
516
517    if(pdcchTime.slot == pdschTime.slot)
518    {
519       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = BOTH;
520       dciSlotAlloc->numSchedInfo++;
521    }
522    else
523    {
524       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
525       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
526       {
527          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
528          if(dlMsgAlloc == NULLP)
529          {
530             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
531             if(dciSlotAlloc->numSchedInfo == 0)
532             {
533                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
534                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
535             }
536             else
537                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
538             return false;
539          }
540          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
541          memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
542          dlMsgAlloc->crnti = dciSlotAlloc->crnti;
543       }
544       else
545          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
546
547       /* Copy all DL_MSG info */
548       memcpy(&dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo], \
549             &dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], sizeof(DlMsgSchInfo));
550       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdcchCfg.dci.pdschCfg = \
551             &dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdschCfg;
552
553       /* Assign correct PDU types in corresponding slots */
554       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].pduPres = PDSCH_PDU;
555       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = PDCCH_PDU;
556       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pdschSlot = pdschTime.slot;
557
558       dciSlotAlloc->numSchedInfo++;
559       dlMsgAlloc->numSchedInfo++;
560    }
561
562    schAllocPucchResource(cell, pucchTime, crnti);
563    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
564    cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
565    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
566
567    /* after allocation is done, unset the bo bit for that ue */
568    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
569  
570    return true;
571 }
572
573 /*******************************************************************
574  *
575  * @brief Handles slot indication at SCH 
576  *
577  * @details
578  *
579  *    Function : schProcessSlotInd
580  *
581  *    Functionality:
582  *     Handles TTI indication received from PHY
583  *
584  * @params[in] 
585  * @return ROK     - success
586  *         RFAILED - failure
587  *
588  * ****************************************************************/
589 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
590 {
591    uint8_t   ueId, ueIdx, ret = ROK;
592    uint16_t  slot;
593    bool      isRarPending = false, isRarScheduled = false;
594    bool      isMsg4Pending = false, isMsg4Scheduled = false;
595    bool      isUlGrantPending = false, isUlGrantScheduled = false;
596    bool      isDlMsgPending = false, isDlMsgScheduled = 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       if(pendingUeNode->node)
659       {
660          ueId = *(uint8_t *)(pendingUeNode->node);
661
662          /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
663           * PUSCH to receive MSG3 as per k0-k2 configuration*/
664          if(cell->raReq[ueId-1] != NULLP)
665          {
666             isRarPending = true;
667             isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
668          }
669
670          /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
671           * PUCCH to receive UL msg as per k0-k1 configuration  */
672          if(cell->raCb[ueId-1].msg4recvd)
673          {
674             isMsg4Pending = true;
675             isMsg4Scheduled = schProcessMsg4Req(cell, *slotInd, ueId);
676          }
677
678          if(isRarPending || isMsg4Pending)
679          {
680             /* If RAR or MSG is successfully scheduled then
681              * remove UE from linked list since no pending msgs for this UE */
682             if(isRarScheduled || isMsg4Scheduled)
683             {
684                SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
685                deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
686             }
687             /* If RAR/MSG4 is pending but couldnt be scheduled then,
688              * put this UE at the end of linked list to be scheduled later */
689             else 
690             {
691                cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
692             }
693          }
694
695          if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
696          {
697             isUlGrantPending = true;
698             isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId);
699          }
700
701          if((cell->boIndBitMap) & (1<<ueId))
702          {
703             isDlMsgPending = true;
704             isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId);
705          }
706          if(!isUlGrantPending && !isDlMsgPending)
707          {
708             /* No action required */  
709          }
710          else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
711          {
712             cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
713          }
714          else
715          {
716             SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
717             deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
718          }
719       }
720    }
721
722    /* Check if any PDU is scheduled at this slot for any UE */
723    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
724    {
725       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
726        * structure to send to MAC */
727       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
728       {
729          slot = dlSchedInfo.schSlotValue.rarTime.slot;
730          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
731          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
732       }
733
734       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
735        * specific interface structure to send to MAC */
736       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
737       {
738          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
739          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
740          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
741       }
742
743    }
744
745    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
746    {
747       slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
748       dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
749       cell->schDlSlotInfo[slot]->ulGrant = NULLP;
750    }
751
752    /* Send msg to MAC */
753    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
754    if(ret != ROK)
755    {
756       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
757       return (ret);
758    }
759
760    schInitDlSlot(cell->schDlSlotInfo[slot]);
761    schUlResAlloc(cell, schInst);
762
763    return ret;
764 }
765
766 /**********************************************************************
767   End of file
768  **********************************************************************/
769
770