3193429c3b687e49aad5d4e7d7c1b830ddbab777
[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       if(*(uint8_t *)cell->ueToBeScheduled.first->node == ueId)
412       {
413          SCH_FREE(cell->ueToBeScheduled.first->node, sizeof(uint8_t));
414          deleteNodeFromLList(&cell->ueToBeScheduled, cell->ueToBeScheduled.first);
415       }
416       UNSET_ONE_BIT(ueId, cell->boIndBitMap);
417
418       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
419       if(dciSlotAlloc->numSchedInfo == 0)
420       {
421          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
422          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
423       }
424       else
425          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
426       return false;
427    }
428
429    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
430    maxFreePRB = searchLargestFreeBlockDL(cell, pdschTime, &startPrb);
431
432    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
433     * the list based on RRM policy*/
434
435    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
436     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
437    if(maxFreePRB != 0)
438    {
439       mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
440       if((ueCb->dlLcPrbEst.dedLcInfo == NULLP) 
441             || ((maxFreePRB <  ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB)))
442       { 
443          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB;
444          DU_LOG("\nWARNING  --> SCH : Only Default Slice is scheduled, sharedPRB Count:%d",\
445                ueCb->dlLcPrbEst.sharedNumPrb);
446
447          /*PRB Alloc for Default LCs*/
448          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
449                &(ueCb->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded);
450       }
451       else
452       {
453          ueCb->dlLcPrbEst.sharedNumPrb = maxFreePRB - ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB;
454
455          /*PRB Alloc for Dedicated LCs*/
456          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
457                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
458
459          /*PRB Alloc for Default LCs*/
460          prbAllocUsingRRMPolicy(&(ueCb->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
461                &(ueCb->dlLcPrbEst.sharedNumPrb), &(ueCb->dlLcPrbEst.dedLcInfo->rsvdDedicatedPRB), &isTxPayloadLenAdded);
462       }
463    }
464
465    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
466     * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
467    if(ueCb->dlLcPrbEst.dedLcInfo != NULLP)
468       updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.dedLcInfo->dedLcList), dciSlotAlloc, &(accumalatedSize));
469
470    updateGrantSizeForBoRpt(&(ueCb->dlLcPrbEst.defLcList), dciSlotAlloc, &(accumalatedSize));
471
472    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
473    if (!accumalatedSize)
474    {
475       if(maxFreePRB == 0)
476       {
477          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
478       }
479       else
480       {
481          /*Schedule the LC for next slot*/
482          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
483       }
484       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
485        * Allocation can be done in next slot*/
486       return false;
487    }
488
489    /*[Step6]: pdcch and pdsch data is filled */
490    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb, pdschStartSymbol, pdschNumSymbols)) != ROK)
491    {
492       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
493
494       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
495       if(dciSlotAlloc->numSchedInfo == 0)
496       {
497          SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
498          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
499       }
500       else
501          memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
502       return false;
503    }
504
505    /* TODO : Update the scheduling byte report for multiple LC based on QCI
506     * and Priority */
507    /* As of now, the total number of bytes scheduled for a slot is divided
508     * equally amongst all LC with pending data. This is avoid starving of any
509     * LC 
510     * */
511 #if 0
512    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
513    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
514       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
515 #endif
516    
517    /* Check if both DCI and DL_MSG are sent in the same slot.
518     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
519
520    if(pdcchTime.slot == pdschTime.slot)
521    {
522       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = BOTH;
523       dciSlotAlloc->numSchedInfo++;
524    }
525    else
526    {
527       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
528       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
529       {
530          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
531          if(dlMsgAlloc == NULLP)
532          {
533             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
534             if(dciSlotAlloc->numSchedInfo == 0)
535             {
536                SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
537                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
538             }
539             else
540                memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
541             return false;
542          }
543          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
544          memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
545          dlMsgAlloc->crnti = dciSlotAlloc->crnti;
546       }
547       else
548          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
549
550       /* Copy all DL_MSG info */
551       memcpy(&dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo], \
552             &dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], sizeof(DlMsgSchInfo));
553       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdcchCfg.dci.pdschCfg = \
554             &dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdschCfg;
555
556       /* Assign correct PDU types in corresponding slots */
557       dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].pduPres = PDSCH_PDU;
558       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = PDCCH_PDU;
559       dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pdschSlot = pdschTime.slot;
560
561       dciSlotAlloc->numSchedInfo++;
562       dlMsgAlloc->numSchedInfo++;
563    }
564
565    schAllocPucchResource(cell, pucchTime, crnti);
566    cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
567    cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
568    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
569
570    /* after allocation is done, unset the bo bit for that ue */
571    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
572  
573    return true;
574 }
575
576 /*******************************************************************
577  *
578  * @brief Handles slot indication at SCH 
579  *
580  * @details
581  *
582  *    Function : schProcessSlotInd
583  *
584  *    Functionality:
585  *     Handles TTI indication received from PHY
586  *
587  * @params[in] 
588  * @return ROK     - success
589  *         RFAILED - failure
590  *
591  * ****************************************************************/
592 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
593 {
594    uint8_t   ueId, ueIdx, ret = ROK;
595    uint16_t  slot;
596    bool      isRarPending = false, isRarScheduled = false;
597    bool      isMsg4Pending = false, isMsg4Scheduled = false;
598    bool      isUlGrantPending = false, isUlGrantScheduled = false;
599    bool      isDlMsgPending = false, isDlMsgScheduled = false;
600    CmLList       *pendingUeNode;
601    DlSchedInfo   dlSchedInfo;
602    DlBrdcstAlloc *dlBrdcstAlloc = NULLP;
603    SchCellCb     *cell = NULLP;
604
605    memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
606    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue);
607    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
608    dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
609    dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
610
611    cell = schCb[schInst].cells[schInst];
612    if(cell == NULLP)
613    {
614       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
615       return RFAILED;
616    }
617    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
618    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
619
620    dlSchedInfo.cellId = cell->cellId;
621    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
622
623    /* Check for SSB occassion */
624    dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
625    if(dlBrdcstAlloc->ssbTrans)
626    {
627       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
628       {
629          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
630          dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
631       }
632       else 
633       {
634          dlSchedInfo.isBroadcastPres = true;
635          if((dlBrdcstAlloc->ssbTrans == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
636             cell->firstSsbTransmitted = true;
637       }
638    }
639
640    /* Check for SIB1 occassion */
641    dlBrdcstAlloc->sib1Trans = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
642    if(dlBrdcstAlloc->sib1Trans)
643    {
644       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
645       {
646          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
647          dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
648       }
649       else 
650       {
651          dlSchedInfo.isBroadcastPres = true;
652          if((dlBrdcstAlloc->sib1Trans == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
653             cell->firstSib1Transmitted = true;
654       }
655    }
656
657    /* Select first UE in the linked list to be scheduled next */
658    pendingUeNode = cell->ueToBeScheduled.first;
659    if(pendingUeNode)
660    {
661       if(pendingUeNode->node)
662       {
663          ueId = *(uint8_t *)(pendingUeNode->node);
664
665          /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
666           * PUSCH to receive MSG3 as per k0-k2 configuration*/
667          if(cell->raReq[ueId-1] != NULLP)
668          {
669             isRarPending = true;
670             isRarScheduled = schProcessRaReq(cell, *slotInd, ueId);
671          }
672
673          /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
674           * PUCCH to receive UL msg as per k0-k1 configuration  */
675          if(cell->raCb[ueId-1].msg4recvd)
676          {
677             isMsg4Pending = true;
678             isMsg4Scheduled = schProcessMsg4Req(cell, *slotInd, ueId);
679          }
680
681          if(isRarPending || isMsg4Pending)
682          {
683             /* If RAR or MSG is successfully scheduled then
684              * remove UE from linked list since no pending msgs for this UE */
685             if(isRarScheduled || isMsg4Scheduled)
686             {
687                SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
688                deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
689             }
690             /* If RAR/MSG4 is pending but couldnt be scheduled then,
691              * put this UE at the end of linked list to be scheduled later */
692             else 
693             {
694                cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
695             }
696          }
697
698          if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
699          {
700             isUlGrantPending = true;
701             isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId);
702          }
703
704          if((cell->boIndBitMap) & (1<<ueId))
705          {
706             isDlMsgPending = true;
707             isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId);
708          }
709          if(!isUlGrantPending && !isDlMsgPending)
710          {
711             /* No action required */  
712          }
713          else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
714          {
715             cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
716          }
717          else
718          {
719             SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
720             deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
721          }
722       }
723    }
724
725    /* Check if any PDU is scheduled at this slot for any UE */
726    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
727    {
728       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
729        * structure to send to MAC */
730       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
731       {
732          slot = dlSchedInfo.schSlotValue.rarTime.slot;
733          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
734          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
735       }
736
737       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
738        * specific interface structure to send to MAC */
739       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
740       {
741          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
742          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
743          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
744       }
745
746    }
747
748    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
749    {
750       slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
751       dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
752       cell->schDlSlotInfo[slot]->ulGrant = NULLP;
753    }
754
755    /* Send msg to MAC */
756    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
757    if(ret != ROK)
758    {
759       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
760       return (ret);
761    }
762
763    schInitDlSlot(cell->schDlSlotInfo[slot]);
764    schUlResAlloc(cell, schInst);
765
766    return ret;
767 }
768
769 /**********************************************************************
770   End of file
771  **********************************************************************/
772
773