1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions for slot indications
29 **********************************************************************/
31 /** @file sch_slot_ind.c
32 @brief This module processes slot indications
34 #include "common_def.h"
40 #include "du_app_mac_inf.h"
41 #include "mac_sch_interface.h"
43 #include "sch_utils.h"
45 SchMacDlAllocFunc schMacDlAllocOpts[] =
52 SchMacDlPageAllocFunc schMacDlPageAllocOpts[] =
54 packSchMacDlPageAlloc,
59 /*******************************************************************
61 * @brief Handles sending DL broadcast alloc to MAC
65 * Function : sendDlAllocToMac
68 * Sends DL Broadcast Resource Allocation to MAC from SCH
71 * @return ROK - success
74 * ****************************************************************/
75 uint8_t sendDlAllocToMac(DlSchedInfo *dlSchedInfo, Inst inst)
79 memset(&pst, 0, sizeof(Pst));
80 FILL_PST_SCH_TO_MAC(pst, inst);
81 pst.event = EVENT_DL_SCH_INFO;
83 return(*schMacDlAllocOpts[pst.selector])(&pst, dlSchedInfo);
87 /*******************************************************************
89 * @brief Handles sending DL Page alloc to MAC
93 * Function : sendDlPAgeAllocToMac
96 * Sends DL Page Resource Allocation to MAC from SCH
99 * @return ROK - success
102 * ****************************************************************/
103 uint8_t sendDlPageAllocToMac(DlPageAlloc *dlPageAlloc, Inst inst)
107 memset(&pst, 0, sizeof(Pst));
108 FILL_PST_SCH_TO_MAC(pst, inst);
109 pst.event = EVENT_DL_PAGING_ALLOC;
111 return(*schMacDlPageAllocOpts[pst.selector])(&pst, dlPageAlloc);
115 /*******************************************************************
117 * @brief Handles slot indication at SCH
121 * Function : schCalcSlotValues
124 * Handles TTI indication received from PHY
127 * @return ROK - success
130 * ****************************************************************/
131 void schCalcSlotValues(SlotTimingInfo slotInd, SchSlotValue *schSlotValue)
133 /****************************************************************
134 * PHY_DELTA - the physical layer delta *
135 * SCHED_DELTA - scheduler schedules one slot ahead *
136 * BO_DELTA - this delay is considered for BO response and *
137 * RLC buffer packet to received at MAC *
138 * lower-mac (FAPI filling) will be working on PHY_DELTA *
139 * brdcast scheduler will working on PHY_DELTA + SCHED_DELTA *
140 * RAR scheduler will working on PHY_DELTA + SCHED_DELTA *
141 * msg4 scheduler will working on PHY_DELTA + SCHED_DELTA *
142 * dedicated DL msg scheduler will working *
143 * on PHY_DELTA + SCHED_DELTA + BO_DELTA *
144 ****************************************************************/
146 ADD_DELTA_TO_TIME(slotInd, schSlotValue->currentTime, PHY_DELTA_DL);
147 ADD_DELTA_TO_TIME(slotInd, schSlotValue->broadcastTime, PHY_DELTA_DL + SCHED_DELTA);
148 ADD_DELTA_TO_TIME(slotInd, schSlotValue->rarTime, PHY_DELTA_DL + SCHED_DELTA);
149 ADD_DELTA_TO_TIME(slotInd, schSlotValue->dlMsgTime, PHY_DELTA_DL + SCHED_DELTA);
150 ADD_DELTA_TO_TIME(slotInd, schSlotValue->ulDciTime, PHY_DELTA_DL + SCHED_DELTA);
153 /*******************************************************************
155 * @brief Checks if a slot is to be scheduled for SSB transmission
159 * Function : schCheckSsbOcc
162 * Checks if a slot is to be scheduled for SSB transmission
164 * @params[in] SlotTimingInfo slotTime
166 * @return Pdu transmission
168 * ****************************************************************/
169 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
173 ssb_rep = cell->cellCfg.ssbSchCfg.ssbPeriod;
175 /* Identify SSB ocassion*/
176 if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
178 return NEW_TRANSMISSION;
180 else if(cell->firstSsbTransmitted)
182 if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
184 else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
187 /* not SSB occassion */
188 return NO_TRANSMISSION;
191 /*******************************************************************
193 * @brief Checks if a slot is to be scheduled for SIB1 transmission
197 * Function : schCheckSib1Occ
200 * Checks if a slot is to be scheduled for SIB1 transmission
202 * @params[in] SlotTimingInfo slotTime
204 * @return Pdu transmission
206 * ****************************************************************/
207 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
209 /* Identify SIB1 occasions */
210 if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
212 return NEW_TRANSMISSION;
214 else if(cell->firstSib1Transmitted)
216 if((slotTime.sfn % (cell->cellCfg.sib1SchCfg.sib1RepetitionPeriod/10) == 0) &&
217 (slotTime.slot == 0))
222 /* not SIB1 occassion */
223 return NO_TRANSMISSION;
226 /*******************************************************************
228 * @brief find correct combination of k0-k1 value
232 * Function : findValidK0K1Value
235 * find correct combination of k0-k1 value
237 * @params[in] SchCellCb *cell, SlotTimingInfo currTime
238 * @params[in] uint8_t ueId, bool dedMsg
239 * @params[in] uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen
240 * @params[in] SlotTimingInfo *pdcchTime, SlotTimingInfo *pdschTime
241 * @params[in] SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP
242 * @return ROK - success
245 *******************************************************************/
246 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg,
247 uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,
248 SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP)
250 uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
251 uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
252 SchUeCb *ueCb = NULLP;
253 SchK0K1TimingInfoTbl *k0K1InfoTbl;
255 ADD_DELTA_TO_TIME(currTime, (*pdcchTime), PHY_DELTA_DL + SCHED_DELTA);
257 if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
259 /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
264 if(cell->schDlSlotInfo[pdcchTime->slot]->pdcchUe != 0)
271 ueCb = &cell->ueCb[ueId-1];
272 k0K1InfoTbl = &ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1InfoTbl;
276 k0K1InfoTbl = &cell->cellCfg.schInitialDlBwp.k0K1InfoTbl;
279 numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
280 for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
282 k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
285 k0Val = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
286 *pdschStartSymbol = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
287 *pdschSymblLen = cell->cellCfg.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
291 if(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
293 k0Val = *(ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
294 *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
295 *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
299 ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val);
301 if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
306 if(cell->schDlSlotInfo[pdschTime->slot]->pdschUe != 0)
311 numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
312 for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
314 k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
317 k1Val = defaultUlAckTbl[k1Index];
321 if(ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck)
323 k1Val = ueCb->ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
326 ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val);
328 if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
333 if(cell->schUlSlotInfo[pucchTime->slot]->pucchUe != 0)
341 * Number of symbols in case of retransmisson should be same as it was in
342 * original transmisson. Symbol availablity checks need to be added.
347 /*******************************************************************
353 * Function : schFillBoGrantDlSchedInfo
358 * @params[in] SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
359 * @params[in] bool isRetx, SchDlHqProcCb **hqP
360 * @return ROK - success
363 * ****************************************************************/
364 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool isRetx, SchDlHqProcCb **hqP)
367 uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
368 uint16_t startPrb = 0, maxFreePRB = 0;
369 uint16_t crnti = 0, mcsIdx = 0;
370 uint32_t accumalatedSize = 0;
371 SchUeCb *ueCb = NULLP;
372 CmLListCp *lcLL = NULLP;
373 DlMsgAlloc *dciSlotAlloc, *dlMsgAlloc;
374 SlotTimingInfo pdcchTime, pdschTime, pucchTime;
375 uint16_t rsvdDedicatedPRB = 0;
377 /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
378 * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
379 * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
380 * else if only Default list is present then first node in this List will add this overhead len*/
381 bool isTxPayloadLenAdded = FALSE;
382 GET_CRNTI(crnti,ueId);
383 ueCb = &cell->ueCb[ueId-1];
387 if(schDlGetAvlHqProcess(cell, ueCb, hqP) != ROK)
393 if(findValidK0K1Value(cell, currTime, ueId, ueCb->ueCfg.spCellCfg.servCellCfg.initDlBwp.k0K1TblPrsnt,\
394 &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, &pucchTime, isRetx, *hqP) != true )
396 /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
397 * not found, do not perform resource allocation. Return from here. */
401 /* allocate PDCCH and PDSCH resources for the ue */
402 if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
405 SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgAlloc));
408 DU_LOG("\nERROR --> SCH : Memory Allocation failed for ded DL msg alloc");
411 cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
412 memset(dciSlotAlloc, 0, sizeof(DlMsgAlloc));
413 dciSlotAlloc->crnti = crnti;
417 dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
419 /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
420 fillDlMsgInfo(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].dlMsgInfo, dciSlotAlloc->crnti, isRetx, *hqP);
421 dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].isRetx = isRetx;
426 /*Re-Initalization per UE*/
427 /* scheduled LC data fill */
428 dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].numLc = 0;
429 isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
432 for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
434 if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
436 /*Check the LC is Dedicated or default and accordingly LCList will
438 if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
440 lcLL = &((*hqP)->dlLcPrbEst.dedLcList);
441 rsvdDedicatedPRB = ueCb->dlInfo.dlLcCtxt[lcIdx].rsvdDedicatedPRB;
445 lcLL = &((*hqP)->dlLcPrbEst.defLcList);
448 /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
449 if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
450 (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
452 DU_LOG("\nERROR --> SCH : Updation in LC List Failed");
453 /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
454 if(dciSlotAlloc->numSchedInfo == 0)
456 SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
457 cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
460 memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
464 ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
466 if (((*hqP)->dlLcPrbEst.defLcList.count == 0) && ( ((*hqP)->dlLcPrbEst.dedLcList.count == 0)))
468 DU_LOG("\nDEBUG --> SCH : No pending BO for any LC id\n");
469 UNSET_ONE_BIT(ueId, cell->boIndBitMap);
471 /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
472 if(dciSlotAlloc->numSchedInfo == 0)
474 SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
475 cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
478 memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
480 /*TRUE because this UE has nothing to be scheduled*/
485 /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
486 maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
488 /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
489 * the list based on RRM policy*/
491 /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or
492 * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
497 mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
499 if(((*hqP)->dlLcPrbEst.dedLcList.count == NULLP)
500 || ((maxFreePRB < rsvdDedicatedPRB)))
502 (*hqP)->dlLcPrbEst.sharedNumPrb = maxFreePRB;
503 DU_LOG("\nDEBUG --> SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
504 (*hqP)->dlLcPrbEst.sharedNumPrb);
506 /*PRB Alloc for Default LCs*/
507 prbAllocUsingRRMPolicy(&((*hqP)->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
508 &((*hqP)->dlLcPrbEst.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
512 (*hqP)->dlLcPrbEst.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
513 /*PRB Alloc for Dedicated LCs*/
514 prbAllocUsingRRMPolicy(&((*hqP)->dlLcPrbEst.dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
515 &((*hqP)->dlLcPrbEst.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
517 /*PRB Alloc for Default LCs*/
518 prbAllocUsingRRMPolicy(&((*hqP)->dlLcPrbEst.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
519 &((*hqP)->dlLcPrbEst.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
524 /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
525 * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/
528 if((*hqP)->dlLcPrbEst.dedLcList.count != 0)
529 updateGrantSizeForBoRpt(&((*hqP)->dlLcPrbEst.dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
531 updateGrantSizeForBoRpt(&((*hqP)->dlLcPrbEst.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
535 accumalatedSize = (*hqP)->tbInfo[0].tbSzReq;
538 /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
539 if (!accumalatedSize)
543 DU_LOG("\nERROR --> SCH : NO FREE PRB!!");
547 /*Schedule the LC for next slot*/
548 DU_LOG("\nDEBUG --> SCH : No LC has been scheduled");
550 /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
551 * Allocation can be done in next slot*/
555 /*[Step6]: pdcch and pdsch data is filled */
556 if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb, pdschStartSymbol, pdschNumSymbols, isRetx, *hqP)) != ROK)
558 DU_LOG("\nERROR --> SCH : Scheduling of DL dedicated message failed");
560 /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
561 if(dciSlotAlloc->numSchedInfo == 0)
563 SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
564 cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
568 memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
573 /* TODO : Update the scheduling byte report for multiple LC based on QCI
575 /* As of now, the total number of bytes scheduled for a slot is divided
576 * equally amongst all LC with pending data. This is avoid starving of any
580 accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
581 for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
582 dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
585 /* Check if both DCI and DL_MSG are sent in the same slot.
586 * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
588 if(pdcchTime.slot == pdschTime.slot)
590 dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = BOTH;
591 dciSlotAlloc->numSchedInfo++;
595 /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
596 if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
598 SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgAlloc));
599 if(dlMsgAlloc == NULLP)
601 DU_LOG("\nERROR --> SCH : Memory Allocation failed for dlMsgAlloc");
602 if(dciSlotAlloc->numSchedInfo == 0)
604 SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
605 cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
608 memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
611 cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
612 memset(dlMsgAlloc, 0, sizeof(DlMsgAlloc));
613 dlMsgAlloc->crnti = dciSlotAlloc->crnti;
616 dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
618 /* Copy all DL_MSG info */
619 memcpy(&dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo], \
620 &dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], sizeof(DlMsgSchInfo));
621 dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdcchCfg.dci.pdschCfg = \
622 &dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].dlMsgPdschCfg;
624 /* Assign correct PDU types in corresponding slots */
625 dlMsgAlloc->dlMsgSchedInfo[dlMsgAlloc->numSchedInfo].pduPres = PDSCH_PDU;
626 dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pduPres = PDCCH_PDU;
627 dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].pdschSlot = pdschTime.slot;
629 dciSlotAlloc->numSchedInfo++;
630 dlMsgAlloc->numSchedInfo++;
633 schAllocPucchResource(cell, pucchTime, crnti, ueCb, isRetx, *hqP);
635 cell->schDlSlotInfo[pdcchTime.slot]->pdcchUe = ueId;
636 cell->schDlSlotInfo[pdschTime.slot]->pdschUe = ueId;
637 cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
639 /* after allocation is done, unset the bo bit for that ue */
640 UNSET_ONE_BIT(ueId, cell->boIndBitMap);
644 /*******************************************************************
646 * @brief Process DL Resource allocation for Page
650 * Function : schProcDlPageAlloc
652 * Functionality: Process DL Resource allocation for Page
654 * @params[in] SchCellCb *cell, SlotTimingInfo currTime, Inst schInst
656 * @return pointer to return Value(ROK, RFAILED)
658 * ****************************************************************/
659 uint8_t schProcDlPageAlloc(SchCellCb *cell, SlotTimingInfo currTime, Inst schInst)
661 DlPageAlloc dlPageAlloc;
662 CmLList *pageInfoNode = NULLP;
663 SchPageInfo *pageInfo = NULLP;
664 SlotTimingInfo pdschTime;
666 uint16_t startPrb = 0, maxFreePRB = 0, nPRB = 0;
667 uint8_t ret = RFAILED;
669 pageInfoNode = schPageInfoSearchFromPageList(currTime, &(cell->pageCb.pageIndInfoRecord[currTime.sfn]));
671 if(pageInfoNode == NULLP)
675 pageInfo = (SchPageInfo *)pageInfoNode->node;
679 dlPageAlloc.cellId = currTime.cellId;
681 ADD_DELTA_TO_TIME(currTime, dlPageAlloc.dlPageTime, PHY_DELTA_DL + SCHED_DELTA);
682 dlPageAlloc.shortMsgInd = FALSE;
683 pdschTime = dlPageAlloc.dlPageTime;
685 /*Calculate Best FREE BLOCK with MAX PRB count*/
686 maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
690 tbSize = calculateEstimateTBSize(pageInfo->msgLen, pageInfo->mcs, NUM_PDSCH_SYMBOL, maxFreePRB, &nPRB);
694 DU_LOG("\nERROR --> SCH: Unable to get any free block for Paging at SFN:%d, SLOT:%d",\
695 pdschTime.sfn, pdschTime.slot);
698 /*Fill PDCCH: PDCCH Cfg is same as SIB1 as Paging will be a broadcast message*/
699 memcpy(&dlPageAlloc.pagePdcchCfg, &cell->cellCfg.sib1SchCfg.sib1PdcchCfg, sizeof(PdcchCfg));
700 dlPageAlloc.pagePdcchCfg.dci.rnti = P_RNTI;
703 memcpy(&dlPageAlloc.bwp, &cell->cellCfg.sib1SchCfg.bwp, sizeof(BwpCfg));
706 if(schFillPagePdschCfg(cell, &dlPageAlloc.pagePdschCfg, pdschTime, tbSize, pageInfo->mcs, startPrb) != ROK)
708 DU_LOG("\nERROR --> SCH: Issue in PDSCH Allocation for Paging at SFN:%d, SLOT:%d",\
709 pdschTime.sfn, pdschTime.slot);
712 dlPageAlloc.pagePdcchCfg.dci.pdschCfg = &dlPageAlloc.pagePdschCfg;
714 /*Fill Page PDU information*/
715 dlPageAlloc.dlPagePduLen = pageInfo->msgLen;
717 SCH_ALLOC(dlPageAlloc.dlPagePdu, sizeof(dlPageAlloc.dlPagePduLen));
719 if(dlPageAlloc.dlPagePdu == NULLP)
721 DU_LOG("\nERROR --> SCH: Memory Allocation Failed during Page Resource allocation");
724 memcpy(dlPageAlloc.dlPagePdu, pageInfo->pagePdu, dlPageAlloc.dlPagePduLen);
726 /* Send msg to MAC */
727 if(sendDlPageAllocToMac(&dlPageAlloc, schInst) != ROK)
729 DU_LOG("\nERROR --> SCH : Sending DL Paging allocation from SCH to MAC failed");
730 SCH_FREE(dlPageAlloc.dlPagePdu, sizeof(dlPageAlloc.dlPagePduLen));
737 /*Remove the Page Node*/
738 SCH_FREE(pageInfo->pagePdu, pageInfo->msgLen);
739 schDeleteFromPageInfoList(&(cell->pageCb.pageIndInfoRecord[currTime.sfn]), pageInfoNode);
745 /*******************************************************************
747 * @brief Handles slot indication at SCH
751 * Function : schProcessSlotInd
754 * Handles TTI indication received from PHY
757 * @return ROK - success
760 * ****************************************************************/
761 uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst)
763 uint8_t ueId, ueIdx, ret = ROK;
765 bool isRarPending = false, isRarScheduled = false;
766 bool isMsg4Pending = false, isMsg4Scheduled = false;
767 bool isUlGrantPending = false, isUlGrantScheduled = false;
768 bool isDlMsgPending = false, isDlMsgScheduled = false;
769 CmLList *pendingUeNode;
770 DlSchedInfo dlSchedInfo;
771 DlBrdcstAlloc *dlBrdcstAlloc = NULLP;
772 SchCellCb *cell = NULLP;
775 SchDlHqProcCb *hqP = NULLP, *ulHqP = NULLP;
777 memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
778 schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue);
779 dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
780 dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
781 dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
783 cell = schCb[schInst].cells[schInst];
786 DU_LOG("\nERROR --> SCH : Cell Does not exist");
789 memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
790 dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
792 dlSchedInfo.cellId = cell->cellId;
793 slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
795 /* Check for SSB occassion */
796 dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime);
797 if(dlBrdcstAlloc->ssbTrans)
799 if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
801 DU_LOG("\nERROR --> SCH : schBroadcastSsbAlloc failed");
802 dlBrdcstAlloc->ssbTrans = NO_TRANSMISSION;
806 dlSchedInfo.isBroadcastPres = true;
807 if((dlBrdcstAlloc->ssbTrans == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
808 cell->firstSsbTransmitted = true;
812 /* Check for SIB1 occassion */
813 dlBrdcstAlloc->sib1Trans = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
814 if(dlBrdcstAlloc->sib1Trans)
816 if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
818 DU_LOG("\nERROR --> SCH : schBroadcastSib1Alloc failed");
819 dlBrdcstAlloc->sib1Trans = NO_TRANSMISSION;
823 dlSchedInfo.isBroadcastPres = true;
824 if((dlBrdcstAlloc->sib1Trans == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
825 cell->firstSib1Transmitted = true;
829 /*Process Paging Msg*/
830 schProcDlPageAlloc(cell, *slotInd, schInst);
832 /* Select first UE in the linked list to be scheduled next */
833 pendingUeNode = cell->ueToBeScheduled.first;
836 if(pendingUeNode->node)
838 ueNode = (uint8_t *)pendingUeNode->node;
839 ueId = *(uint8_t *)(pendingUeNode->node);
840 /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and
841 * PUSCH to receive MSG3 as per k0-k2 configuration*/
842 if(cell->raReq[ueId-1] != NULLP)
845 isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
848 /*MSG3 retransmisson*/
849 if(cell->raCb[ueId-1].retxMsg3HqProc)
851 schMsg3RetxSchedulingForUe(&(cell->raCb[ueId-1]));
854 /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
855 * PUCCH to receive UL msg as per k0-k1 configuration */
856 if (cell->ueCb[ueId-1].retxMsg4HqProc) //should work from dlmap later tbd
858 /* Retransmission of MSG4 */
859 isMsg4Pending = true;
860 if(schProcessMsg4Req(cell, *slotInd, ueId, TRUE, &cell->ueCb[ueId-1].retxMsg4HqProc) == ROK)
861 isMsg4Scheduled = true;
865 /* First transmission of MSG4 */
866 if(cell->raCb[ueId-1].msg4recvd)
868 isMsg4Pending = true;
869 if(schProcessMsg4Req(cell, *slotInd, ueId, FALSE, &cell->ueCb[ueId-1].msg4Proc) == ROK)
870 isMsg4Scheduled = true;
872 /* If MSG4 scheduling failed, free the newly assigned HARQ process */
874 schDlReleaseHqProcess(cell->ueCb[ueId-1].msg4Proc);
878 if(isRarPending || isMsg4Pending)
880 /* If RAR or MSG is successfully scheduled then
881 * remove UE from linked list since no pending msgs for this UE */
882 if(isRarScheduled || isMsg4Scheduled)
884 SCH_FREE(pendingUeNode->node, sizeof(uint8_t));
885 deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
887 /* If RAR/MSG4 is pending but couldnt be scheduled then,
888 * put this UE at the end of linked list to be scheduled later */
891 cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
896 node = cell->ueCb[ueId-1].dlRetxHqList.first;
899 /* DL Data ReTransmisson */
900 isDlMsgPending = true;
901 isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, TRUE, ((SchDlHqProcCb**) &(node->node)));
902 cmLListDelFrm(&cell->ueCb[ueId-1].dlRetxHqList, node);
906 /* DL Data new transmission */
907 if((cell->boIndBitMap) & (1<<ueId))
909 isDlMsgPending = true;
910 isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, FALSE, &hqP);
912 /* If DL scheduling failed, free the newly assigned HARQ process */
913 if(!isDlMsgScheduled)
914 schDlReleaseHqProcess(hqP);
918 /* Scheduling of UL grant */
919 node = cell->ueCb[ueId-1].ulRetxHqList.first;
922 /* UL Data ReTransmisson */
923 isUlGrantPending = true;
924 isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, TRUE, (SchUlHqProcCb**) &(node->node));
925 cmLListDelFrm(&cell->ueCb[ueId-1].ulRetxHqList, node);
929 /* UL Data new transmission */
930 if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
932 isUlGrantPending = true;
933 isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, FALSE, &ulHqP);
934 if(!isUlGrantScheduled)
935 schUlReleaseHqProcess(ulHqP, FALSE);
939 if(!isUlGrantPending && !isDlMsgPending)
941 /* No action required */
943 else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
945 cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode));
949 SCH_FREE(ueNode, sizeof(uint8_t));
950 deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode);
955 /* Check if any PDU is scheduled at this slot for any UE */
956 for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
958 /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface
959 * structure to send to MAC */
960 if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
962 slot = dlSchedInfo.schSlotValue.rarTime.slot;
963 dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
964 cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
967 /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill
968 * specific interface structure to send to MAC */
969 if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
971 slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
972 dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
973 cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
977 if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
979 slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
980 dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
981 cell->schDlSlotInfo[slot]->ulGrant = NULLP;
984 /* Send msg to MAC */
985 ret = sendDlAllocToMac(&dlSchedInfo, schInst);
988 DU_LOG("\nERROR --> SCH : Sending DL Broadcast allocation from SCH to MAC failed");
992 schInitDlSlot(cell->schDlSlotInfo[slot]);
993 schUlResAlloc(cell, schInst);
998 /**********************************************************************
1000 **********************************************************************/