Merge "[Epic-ID: ODUHIGH-517][Task-ID: ODUHIGH-540][SubTask-Id: ODUHIGH-549] Multi...
[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_tmr.h"
44 #include "sch_utils.h"
45 #ifdef NR_DRX 
46 #include "sch_drx.h"
47 #endif
48
49 /*******************************************************************
50  *
51  * @brief Handles sending DL broadcast alloc to MAC 
52  *
53  * @details
54  *
55  *    Function : sendDlAllocToMac
56  *
57  *    Functionality:
58  *     Sends DL Broadcast Resource Allocation to MAC from SCH
59  *
60  * @params[in] 
61  * @return ROK     - success
62  *         RFAILED - failure
63  *
64  * ****************************************************************/
65 uint8_t sendDlAllocToMac(DlSchedInfo *dlSchedInfo, Inst inst)
66 {
67    Pst pst;
68
69    memset(&pst, 0, sizeof(Pst));
70    FILL_PST_SCH_TO_MAC(pst, inst);
71    pst.event = EVENT_DL_SCH_INFO;
72
73    return(MacMessageRouter(&pst, (void *)dlSchedInfo));
74 }
75
76 /*******************************************************************
77  *
78  * @brief 
79  *
80  * @details
81  *
82  *    Function : schFillBoGrantDlSchedInfo 
83  *
84  *    Functionality:
85  
86  *
87  * @params[in] SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId
88  * @params[in] bool isRetx, SchDlHqProcCb **hqP
89  * @return ROK     - success
90  *         RFAILED - failure
91  *
92  * ****************************************************************/
93 bool schFillBoGrantDlSchedInfo(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool isRetx, SchDlHqProcCb **hqP)
94 {
95    uint8_t pdschNumSymbols = 0, pdschStartSymbol = 0;
96    uint8_t lcIdx = 0;
97    uint16_t startPrb = 0;
98    uint16_t crnti = 0;
99    uint32_t accumalatedSize = 0;
100    SchUeCb *ueCb = NULLP;
101    DlMsgSchInfo *dciSlotAlloc, *dlMsgAlloc;
102    SlotTimingInfo pdcchTime, pdschTime, pucchTime;
103    SchPdcchAllocInfo pdcchAllocInfo;
104
105    GET_CRNTI(crnti,ueId);
106    ueCb = &cell->ueCb[ueId-1];
107
108    if (isRetx == FALSE)
109    {
110       if(schDlGetAvlHqProcess(cell, ueCb, hqP) != ROK)
111       {
112          return false;
113       }
114    }
115
116    memset(&pdcchAllocInfo,0,sizeof(SchPdcchAllocInfo));
117    if(findValidK0K1Value(cell, currTime, ueId, ueCb->k0K1TblPrsnt,\
118             &pdschStartSymbol, &pdschNumSymbols, &pdcchTime, &pdschTime, \
119             &pucchTime, isRetx, *hqP, &pdcchAllocInfo) != true )
120    {
121       /* If a valid combination of slots to scheduled PDCCH, PDSCH and PUCCH is
122        * not found, do not perform resource allocation. Return from here. */
123       return false;
124    }
125    
126    /* allocate PDCCH and PDSCH resources for the ue */
127    if(cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] == NULL)
128    {
129
130       SCH_ALLOC(dciSlotAlloc, sizeof(DlMsgSchInfo));
131       if(!dciSlotAlloc)
132       {
133          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for ded DL msg alloc");
134          return false;
135       }
136       cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = dciSlotAlloc;
137       memset(dciSlotAlloc, 0, sizeof(DlMsgSchInfo));
138    }
139    else
140    {
141       dciSlotAlloc = cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1];
142    }
143    /* Dl ded Msg info is copied, this was earlier filled in macSchDlRlcBoInfo */
144    fillDlMsgInfo(dciSlotAlloc, crnti, isRetx, *hqP);
145    dciSlotAlloc->transportBlock[0].ndi = isRetx;
146
147    accumalatedSize = cell->api->SchScheduleDlLc(pdcchTime, pdschTime, pdschNumSymbols, &startPrb, isRetx, hqP);
148
149    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
150    if (!accumalatedSize)
151       return false;
152
153    /*[Step6]: pdcch and pdsch data is filled */
154    if((schDlRsrcAllocDlMsg(cell, pdschTime, crnti, accumalatedSize, dciSlotAlloc, startPrb,\
155                            pdschStartSymbol, pdschNumSymbols, isRetx, *hqP, pdcchAllocInfo)) != ROK)
156    {
157       DU_LOG("\nERROR  --> SCH : Scheduling of DL dedicated message failed");
158
159       /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
160       if(!dciSlotAlloc->dlMsgPdschCfg)
161       {
162          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
163          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId -1] = NULL;
164       }
165       return false;
166    }
167
168    /* TODO : Update the scheduling byte report for multiple LC based on QCI
169     * and Priority */
170    /* As of now, the total number of bytes scheduled for a slot is divided
171     * equally amongst all LC with pending data. This is avoid starving of any
172     * LC 
173     * */
174 #if 0
175    accumalatedSize = accumalatedSize/dlMsgAlloc->numLc;
176    for(lcIdx = 0; lcIdx < dlMsgAlloc->numLc; lcIdx ++)
177       dlMsgAlloc->lcSchInfo[lcIdx].schBytes = accumalatedSize;
178 #endif
179    
180    /* Check if both DCI and DL_MSG are sent in the same slot.
181     * If not, allocate memory for DL_MSG PDSCH slot to store PDSCH info */
182
183    if(pdcchTime.slot == pdschTime.slot)
184    {
185       SCH_ALLOC(dciSlotAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
186       if(!dciSlotAlloc->dlMsgPdschCfg)
187       {
188          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciSlotAlloc->dlMsgPdschCfg");
189          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
190          SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
191          cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
192          return false;
193       }
194       memcpy(dciSlotAlloc->dlMsgPdschCfg,\
195          &dciSlotAlloc->dlMsgPdcchCfg->dci[dciSlotAlloc->dlMsgPdcchCfg->numDlDci - 1].pdschCfg,  sizeof(PdschCfg));
196    }
197    else
198    {
199       /* Allocate memory to schedule dlMsgAlloc to send DL_Msg, pointer will be checked at schProcessSlotInd() */
200       if(cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] == NULLP)
201       {
202          SCH_ALLOC(dlMsgAlloc, sizeof(DlMsgSchInfo));
203          if(dlMsgAlloc == NULLP)
204          {
205             DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc");
206             SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));
207             if(dciSlotAlloc->dlMsgPdschCfg == NULLP)
208             {
209                SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
210                cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
211             }
212             return false;
213          }
214          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = dlMsgAlloc;
215          memset(dlMsgAlloc, 0, sizeof(DlMsgSchInfo));
216       }
217       else
218          dlMsgAlloc = cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1];
219
220       /* Copy all DL_MSG info */
221       dlMsgAlloc->crnti =crnti;
222       dlMsgAlloc->bwp = dciSlotAlloc->bwp;
223       SCH_ALLOC(dlMsgAlloc->dlMsgPdschCfg, sizeof(PdschCfg));
224       if(dlMsgAlloc->dlMsgPdschCfg)
225       {
226          memcpy(dlMsgAlloc->dlMsgPdschCfg,\
227                 &dciSlotAlloc->dlMsgPdcchCfg->dci[dciSlotAlloc->dlMsgPdcchCfg->numDlDci - 1].pdschCfg, sizeof(PdschCfg));
228       }
229       else
230       {
231          SCH_FREE(dciSlotAlloc->dlMsgPdcchCfg, sizeof(PdcchCfg));    
232          if(dciSlotAlloc->dlMsgPdschCfg == NULLP)
233          {
234             SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
235             cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
236
237          }
238          SCH_FREE(dlMsgAlloc, sizeof(DlMsgSchInfo));
239          cell->schDlSlotInfo[pdschTime.slot]->dlMsgAlloc[ueId-1] = NULLP;
240          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dlMsgAlloc->dlMsgPdschCfg");
241          return false;
242       }
243    }
244
245    schAllocPucchResource(cell, pucchTime, crnti, ueCb, isRetx, *hqP);
246
247    cell->schUlSlotInfo[pucchTime.slot]->pucchUe = ueId;
248
249    /*Re-setting the BO's of all DL LCs in this UE*/
250    for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
251    {
252       ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
253    }
254
255    /* after allocation is done, unset the bo bit for that ue */
256    UNSET_ONE_BIT(ueId, cell->boIndBitMap);
257    return true;
258 }
259
260 /*******************************************************************
261  *
262  * @brief Handles sending DL Page alloc to MAC 
263  *
264  * @details
265  *
266  *    Function : sendDlPAgeAllocToMac
267  *
268  *    Functionality:
269  *     Sends DL Page Resource Allocation to MAC from SCH
270  *
271  * @params[in] 
272  * @return ROK     - success
273  *         RFAILED - failure
274  *
275  * ****************************************************************/
276 uint8_t sendDlPageAllocToMac(DlPageAlloc *dlPageAlloc, Inst inst)
277 {
278    Pst pst;
279
280    memset(&pst, 0, sizeof(Pst));
281    FILL_PST_SCH_TO_MAC(pst, inst);
282    pst.event = EVENT_DL_PAGING_ALLOC;
283
284    return(MacMessageRouter(&pst, (void *)dlPageAlloc));
285 }
286
287 /*******************************************************************
288  *
289  * @brief Handles slot indication at SCH 
290  *
291  * @details
292  *
293  *    Function : schCalcSlotValues
294  *
295  *    Functionality:
296  *     Handles TTI indication received from PHY
297  *
298  * @params[in] 
299  * @return ROK     - success
300  *         RFAILED - failure
301  *
302  * ****************************************************************/
303 void schCalcSlotValues(SlotTimingInfo slotInd, SchSlotValue *schSlotValue, uint16_t numOfSlots)
304 {
305    /****************************************************************
306     * PHY_DELTA - the physical layer delta                         * 
307     * SCHED_DELTA - scheduler schedules one slot ahead             *
308     * BO_DELTA - this delay is considered for BO response and      *
309     *            RLC buffer packet to received at MAC              *
310     * lower-mac (FAPI filling) will be working on PHY_DELTA        *
311     * brdcast scheduler will working on PHY_DELTA + SCHED_DELTA    *
312     * RAR scheduler will working on PHY_DELTA + SCHED_DELTA        *
313     * msg4 scheduler will working on PHY_DELTA + SCHED_DELTA       *
314     * dedicated DL msg scheduler will working                      *
315     *        on PHY_DELTA + SCHED_DELTA + BO_DELTA                 *
316     ****************************************************************/
317
318    ADD_DELTA_TO_TIME(slotInd, schSlotValue->currentTime, PHY_DELTA_DL, numOfSlots);
319    ADD_DELTA_TO_TIME(slotInd, schSlotValue->broadcastTime, PHY_DELTA_DL + SCHED_DELTA, numOfSlots);
320    ADD_DELTA_TO_TIME(slotInd, schSlotValue->rarTime, PHY_DELTA_DL + SCHED_DELTA, numOfSlots);
321    ADD_DELTA_TO_TIME(slotInd, schSlotValue->dlMsgTime, PHY_DELTA_DL + SCHED_DELTA, numOfSlots);
322    ADD_DELTA_TO_TIME(slotInd, schSlotValue->ulDciTime, PHY_DELTA_DL + SCHED_DELTA, numOfSlots);
323 }
324
325 /*******************************************************************
326  *
327  * @brief Checks if a slot is to be scheduled for SSB transmission
328  *
329  * @details
330  *
331  *    Function : schCheckSsbOcc 
332  *
333  *    Functionality:
334  *       Checks if a slot is to be scheduled for SSB transmission
335  *
336  * @params[in] SlotTimingInfo slotTime
337  *             SchCellCb *cell 
338  * @return  Pdu transmission 
339  *
340  * ****************************************************************/
341 PduTxOccsaion schCheckSsbOcc(SchCellCb *cell, SlotTimingInfo slotTime)
342 {
343    uint8_t  ssb_rep;
344
345    ssb_rep = cell->cellCfg.ssbPeriod;
346
347    /* Identify SSB ocassion*/
348    if ((slotTime.sfn % SCH_MIB_TRANS == 0) && (slotTime.slot ==0))
349    {
350       return NEW_TRANSMISSION;
351    }
352    else if(cell->firstSsbTransmitted) 
353    {
354       if((ssb_rep == 5) && ((slotTime.slot == 0 || slotTime.slot == 10)))
355          return REPEATITION;
356       else if((slotTime.sfn % (ssb_rep/10) == 0) && slotTime.slot == 0)
357          return REPEATITION;
358    }
359    /* not SSB occassion */
360    return NO_TRANSMISSION;
361 }
362
363 /*******************************************************************
364  *
365  * @brief Checks if a slot is to be scheduled for SIB1 transmission
366  *
367  * @details
368  *
369  *    Function : schCheckSib1Occ
370  *
371  *    Functionality:
372  *       Checks if a slot is to be scheduled for SIB1 transmission
373  *
374  * @params[in] SlotTimingInfo slotTime
375  *             SchCellCb *cell
376  * @return  Pdu transmission
377  *
378  * ****************************************************************/
379 PduTxOccsaion schCheckSib1Occ(SchCellCb *cell, SlotTimingInfo slotTime)
380 {
381    /* Identify SIB1 occasions */
382    if((slotTime.sfn % SCH_SIB1_TRANS == 0) && (slotTime.slot ==0))
383    {
384       return NEW_TRANSMISSION;
385    }
386    else if(cell->firstSib1Transmitted) 
387    {
388       if((slotTime.sfn % (SIB1_REPETITION_PERIOD/10) == 0) &&
389             (slotTime.slot == 0))
390       {
391          return REPEATITION;
392       }
393    }
394    /* not SIB1 occassion */
395    return NO_TRANSMISSION;
396 }
397
398 /*******************************************************************
399  *
400  * @brief find correct combination of k0-k1 value
401  *
402  * @details
403  *
404  *    Function : findValidK0K1Value
405  *
406  *    Functionality:
407  *       find correct combination of k0-k1 value
408  *
409  * @params[in] SchCellCb *cell, SlotTimingInfo currTime
410  * @params[in] uint8_t ueId, bool dedMsg
411  * @params[in] uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen
412  * @params[in] SlotTimingInfo *pdcchTime, SlotTimingInfo *pdschTime
413  * @params[in] SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP
414  * @return ROK     - success
415  *         RFAILED - failure
416  *
417  *******************************************************************/
418 bool findValidK0K1Value(SchCellCb *cell, SlotTimingInfo currTime, uint8_t ueId, bool dedMsg,
419                         uint8_t *pdschStartSymbol, uint8_t *pdschSymblLen, SlotTimingInfo *pdcchTime,
420                         SlotTimingInfo *pdschTime, SlotTimingInfo *pucchTime, bool isRetx, SchDlHqProcCb *hqP,
421                         SchPdcchAllocInfo *pdcchAllocInfo)
422 {
423    uint8_t numK0 = 0, k0TblIdx = 0, k0Val = 0, k0Index =0 ;
424    uint8_t k1TblIdx = 0, k1Index = 0, k1Val = 0, numK1 = 0;
425    SchUeCb *ueCb = NULLP;
426    SchK0K1TimingInfoTbl *k0K1InfoTbl;
427
428    ADD_DELTA_TO_TIME(currTime, (*pdcchTime), PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
429 #ifdef NR_TDD
430    if(schGetSlotSymbFrmt(pdcchTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
431    {
432       /* If it is not a DL slot, cannot schedule PDCCH. Return from here. */
433       return false;
434    }
435 #endif
436
437    if(dedMsg == true)
438    {
439       ueCb = &cell->ueCb[ueId-1];
440       k0K1InfoTbl = &ueCb->k0K1InfoTbl;
441       if(schDlCandidateSelection(ueCb, *pdcchTime, pdcchAllocInfo) == false)
442       {
443         DU_LOG("\nDEBUG  --> SCH: DL candidate Selection failed bcz PDCCH is unavailable for this slot");
444         return false;     
445       }
446    }
447    else
448    {
449       k0K1InfoTbl = &cell->k0K1InfoTbl;
450    }
451
452    numK0 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].numK0;
453    for(k0TblIdx = 0; k0TblIdx < numK0; k0TblIdx++)
454    {
455       k0Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k0Index;
456       if(dedMsg != true)
457       {
458          k0Val = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
459          *pdschStartSymbol = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
460          *pdschSymblLen = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
461       }
462       else
463       {
464          if(ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0 != NULLP)
465          {
466             k0Val = *(ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].k0);
467             *pdschStartSymbol = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].startSymbol;
468             *pdschSymblLen = ueCb->ueCfg.spCellCfg.servCellRecfg.initDlBwp.pdschCfg.timeDomRsrcAllociList[k0Index].symbolLength;
469          }
470          else
471          {
472             k0Val = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].k0;
473             *pdschStartSymbol = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].startSymbol;
474             *pdschSymblLen = cell->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon.timeDomRsrcAllocList[k0Index].lengthSymbol;
475          }
476       }
477
478       ADD_DELTA_TO_TIME((*pdcchTime), (*pdschTime), k0Val, cell->numSlots);
479 #ifdef NR_TDD
480       if(schGetSlotSymbFrmt(pdschTime->slot, cell->slotFrmtBitMap) != DL_SLOT)
481       {
482          continue;
483       }
484 #endif
485
486       numK1 = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.numK1;
487       for(k1TblIdx = 0; k1TblIdx < numK1; k1TblIdx++)
488       {
489          k1Index = k0K1InfoTbl->k0k1TimingInfo[pdcchTime->slot].k0Indexes[k0TblIdx].k1TimingInfo.k1Indexes[k1TblIdx];
490          if(dedMsg != true)
491          {
492             k1Val = defaultUlAckTbl[k1Index];
493          }
494          else
495          {
496             if(ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg.dlDataToUlAck)
497             {
498                k1Val = ueCb->ueCfg.spCellCfg.servCellRecfg.initUlBwp.pucchCfg.dlDataToUlAck->dlDataToUlAckList[k1Index];
499             }
500             else
501             {
502                k1Val = defaultUlAckTbl[k1Index];
503             }
504          }
505          ADD_DELTA_TO_TIME((*pdschTime),(*pucchTime), k1Val, cell->numSlots);
506 #ifdef NR_TDD
507          if(schGetSlotSymbFrmt(pucchTime->slot, cell->slotFrmtBitMap) == DL_SLOT)
508          {
509             continue;
510          }
511 #endif
512          if(cell->schUlSlotInfo[pucchTime->slot]->pucchUe != 0)
513          {
514             continue; 
515          }
516          if(hqP)
517          {
518             ADD_DELTA_TO_TIME((*pucchTime), hqP->pucchTime, 0, cell->numSlots);
519          }
520          pdcchTime->cellId = cell->cellId;
521          pdschTime->cellId = cell->cellId;
522
523          return true;
524       }
525    }
526    /*
527     * Number of symbols in case of retransmisson should be same as it was in
528     * original transmisson. Symbol availablity checks need to be added.
529     */
530    return false;
531 }
532
533 /*******************************************************************
534 *
535 * @brief Process DL Resource allocation for Page
536 *
537 * @details
538 *
539 *    Function : schProcDlPageAlloc
540 *
541 *    Functionality: Process DL Resource allocation for Page
542 *
543 * @params[in] SchCellCb *cell, SlotTimingInfo currTime, Inst schInst
544 *
545 * @return pointer to return Value(ROK, RFAILED)
546 *
547 * ****************************************************************/
548 uint8_t schProcDlPageAlloc(SchCellCb *cell, SlotTimingInfo currTime, Inst schInst)
549 {
550    DlPageAlloc      dlPageAlloc;
551    CmLList          *pageInfoNode = NULLP;
552    SchPageInfo      *pageInfo = NULLP;
553    SlotTimingInfo   pdschTime;
554    uint32_t         tbSize = 0;
555    uint16_t         startPrb = 0, maxFreePRB = 0, nPRB = 0;
556    uint8_t          ret = RFAILED;
557
558    pageInfoNode = schPageInfoSearchFromPageList(currTime, &(cell->pageCb.pageIndInfoRecord[currTime.sfn]));
559
560    if(pageInfoNode == NULLP)
561    {
562       return ROK;
563    }
564    pageInfo = (SchPageInfo *)pageInfoNode->node;
565    
566    while(true)
567    {
568       dlPageAlloc.cellId = currTime.cellId;
569
570       ADD_DELTA_TO_TIME(currTime, dlPageAlloc.dlPageTime, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
571       dlPageAlloc.shortMsgInd  = FALSE;
572       pdschTime = dlPageAlloc.dlPageTime;
573
574       /*Calculate Best FREE BLOCK with MAX PRB count*/
575       maxFreePRB = searchLargestFreeBlock(cell, pdschTime, &startPrb, DIR_DL);
576
577       if(maxFreePRB != 0)
578       {
579          tbSize = calculateEstimateTBSize(pageInfo->msgLen, pageInfo->mcs, NUM_PDSCH_SYMBOL, maxFreePRB, &nPRB);
580       }
581       else
582       {
583          DU_LOG("\nERROR  --> SCH: Unable to get any free block for Paging at SFN:%d, SLOT:%d",\
584                pdschTime.sfn, pdschTime.slot);
585          break;
586       }
587       /*Fill PDCCH: PDCCH Cfg is same as SIB1 as Paging will be a broadcast message*/
588       memcpy(dlPageAlloc.pageDlDci.freqDomainResource, cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.freqDomainResource, 6 * sizeof(uint8_t));
589       dlPageAlloc.pageDlDci.durationSymbols = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.durationSymbols;
590       dlPageAlloc.pageDlDci.cceRegMappingType = INTERLEAVED_CCE_REG_MAPPING;
591       dlPageAlloc.pageDlDci.cceReg.interleaved.regBundleSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.regBundleSize;
592       dlPageAlloc.pageDlDci.cceReg.interleaved.interleaverSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.interleaverSize;
593       dlPageAlloc.pageDlDci.cceReg.interleaved.shiftIndex = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.shiftIndex;
594       dlPageAlloc.pageDlDci.ssStartSymbolIndex = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.startSymbolIndex;
595       dlPageAlloc.pageDlDci.cceIndex = cell->sib1SchCfg.sib1PdcchCfg.dci[0].cceIndex;
596       dlPageAlloc.pageDlDci.aggregLevel = cell->sib1SchCfg.sib1PdcchCfg.dci[0].aggregLevel;
597       dlPageAlloc.pageDlDci.precoderGranularity = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.precoderGranularity;
598       dlPageAlloc.pageDlDci.coreSetSize = cell->sib1SchCfg.sib1PdcchCfg.coresetCfg.coreSetSize;
599       /*Fill BWP*/
600       memcpy(&dlPageAlloc.bwp, &cell->sib1SchCfg.bwp, sizeof(BwpCfg)); 
601
602       /*Fill PDSCH*/
603       if(schFillPagePdschCfg(cell, &dlPageAlloc.pageDlSch, pdschTime, tbSize, pageInfo->mcs, startPrb) != ROK)
604       {
605          DU_LOG("\nERROR  --> SCH: Issue in PDSCH Allocation for Paging at SFN:%d, SLOT:%d",\
606                pdschTime.sfn, pdschTime.slot);
607          break;
608       }
609
610       /*Fill Page PDU information*/
611       dlPageAlloc.pageDlSch.dlPagePduLen = pageInfo->msgLen;
612
613       SCH_ALLOC(dlPageAlloc.pageDlSch.dlPagePdu, sizeof(dlPageAlloc.pageDlSch.dlPagePduLen));
614
615       if(dlPageAlloc.pageDlSch.dlPagePdu == NULLP)
616       {
617          DU_LOG("\nERROR  --> SCH: Memory Allocation Failed during Page Resource allocation");
618          break;
619       }
620       memcpy(dlPageAlloc.pageDlSch.dlPagePdu, pageInfo->pagePdu, dlPageAlloc.pageDlSch.dlPagePduLen);
621
622       /* Send msg to MAC */
623       if(sendDlPageAllocToMac(&dlPageAlloc, schInst) != ROK)
624       {
625          DU_LOG("\nERROR  -->  SCH : Sending DL Paging allocation from SCH to MAC failed");
626          SCH_FREE(dlPageAlloc.pageDlSch.dlPagePdu, sizeof(dlPageAlloc.pageDlSch.dlPagePduLen));
627          break;
628       }
629       ret = ROK;
630       break;
631    }
632
633    /*Remove the Page Node*/
634    SCH_FREE(pageInfo->pagePdu, pageInfo->msgLen);
635    schDeleteFromPageInfoList(&(cell->pageCb.pageIndInfoRecord[currTime.sfn]), pageInfoNode);
636
637    return(ret);
638
639 }
640
641 /*******************************************************************
642  *
643  * @brief Handles slot indication at SCH 
644  *
645  * @details
646  *
647  *    Function : SchProcSlotInd
648  *
649  *    Functionality:
650  *     Handles TTI indication received from PHY
651  *
652  * @params[in] 
653  * @return ROK     - success
654  *         RFAILED - failure
655  *
656  * ****************************************************************/
657 uint8_t SchProcSlotInd(Pst *pst, SlotTimingInfo *slotInd)
658 {
659    uint8_t        ueIdx, ret = ROK;
660    uint16_t       slot;
661    DlSchedInfo    dlSchedInfo;
662    DlBrdcstAlloc  *dlBrdcstAlloc = NULLP;
663    SchCellCb      *cell = NULLP;
664    Inst           schInst = pst->dstInst-SCH_INST_START;
665    CmLList        *node = NULLP;
666    TotalPrbUsage  *dlTotalPrbUsage = NULLP;
667
668    cell = schCb[schInst].cells[schInst];
669    if(cell == NULLP)
670    {
671       DU_LOG("\nERROR  -->  SCH : Cell Does not exist");
672       return RFAILED;
673    }
674    memset(&dlSchedInfo, 0, sizeof(DlSchedInfo));
675    schCalcSlotValues(*slotInd, &dlSchedInfo.schSlotValue, cell->numSlots);
676    dlBrdcstAlloc = &dlSchedInfo.brdcstAlloc;
677    dlBrdcstAlloc->ssbTransmissionMode = NO_TRANSMISSION;
678    dlBrdcstAlloc->sib1TransmissionMode = NO_TRANSMISSION;
679
680    memcpy(&cell->slotInfo, slotInd, sizeof(SlotTimingInfo));
681    dlBrdcstAlloc->ssbIdxSupported = SSB_IDX_SUPPORTED;
682
683    dlSchedInfo.cellId = cell->cellId;
684    slot = dlSchedInfo.schSlotValue.broadcastTime.slot;
685
686 #ifdef NR_DRX 
687    schHandleStartDrxTimer(cell);
688 #endif
689    
690    /* Check for SSB occassion */
691    dlBrdcstAlloc->ssbTransmissionMode = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); 
692    if(dlBrdcstAlloc->ssbTransmissionMode)
693    {
694       if(schBroadcastSsbAlloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
695       {
696          DU_LOG("\nERROR  -->  SCH : schBroadcastSsbAlloc failed");
697          dlBrdcstAlloc->ssbTransmissionMode = NO_TRANSMISSION;
698       }
699       else 
700       {
701          dlSchedInfo.isBroadcastPres = true;
702          if((dlBrdcstAlloc->ssbTransmissionMode == NEW_TRANSMISSION) && (!cell->firstSsbTransmitted))
703             cell->firstSsbTransmitted = true;
704       }
705    }
706
707    /* Check for SIB1 occassion */
708    dlBrdcstAlloc->sib1TransmissionMode = schCheckSib1Occ(cell, dlSchedInfo.schSlotValue.broadcastTime);
709    if(dlBrdcstAlloc->sib1TransmissionMode)
710    {
711       if(schBroadcastSib1Alloc(cell, dlSchedInfo.schSlotValue.broadcastTime, dlBrdcstAlloc) != ROK)
712       {
713          DU_LOG("\nERROR  -->  SCH : schBroadcastSib1Alloc failed");
714          dlBrdcstAlloc->sib1TransmissionMode = NO_TRANSMISSION;
715       }
716       else 
717       {
718          dlSchedInfo.isBroadcastPres = true;
719          if((dlBrdcstAlloc->sib1TransmissionMode == NEW_TRANSMISSION) && (!cell->firstSib1Transmitted))
720             cell->firstSib1Transmitted = true;
721       }
722    }
723
724    /*Process Paging Msg*/
725    schProcDlPageAlloc(cell, *slotInd, schInst);
726
727    cell->api->SchScheduleSlot(cell, slotInd, schInst);
728
729    /* Check if any PDU is scheduled at this slot for any UE */
730    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
731    {
732       /* If RAR PDCCH/PDSCH is scheduled for a UE at this slot, fill RAR specific interface 
733        * structure to send to MAC */
734       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.rarTime.slot]->rarAlloc[ueIdx] != NULLP)
735       {
736          slot = dlSchedInfo.schSlotValue.rarTime.slot;
737          dlSchedInfo.rarAlloc[ueIdx] = cell->schDlSlotInfo[slot]->rarAlloc[ueIdx];
738          cell->schDlSlotInfo[slot]->rarAlloc[ueIdx] = NULLP;
739       }
740
741       /* If DL-Msg PDCCH/PDSCH is scheduled for a UE at this slot, fill 
742        * specific interface structure to send to MAC */
743       if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.dlMsgTime.slot]->dlMsgAlloc[ueIdx] != NULLP)
744       {
745          slot = dlSchedInfo.schSlotValue.dlMsgTime.slot;
746          dlSchedInfo.dlMsgAlloc[ueIdx] = cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx];
747          cell->schDlSlotInfo[slot]->dlMsgAlloc[ueIdx] = NULLP;
748       }
749    }
750
751    if(cell->schDlSlotInfo[dlSchedInfo.schSlotValue.ulDciTime.slot]->ulGrant != NULLP)
752    {
753       slot = dlSchedInfo.schSlotValue.ulDciTime.slot;
754       dlSchedInfo.ulGrant = cell->schDlSlotInfo[slot]->ulGrant;
755       cell->schDlSlotInfo[slot]->ulGrant = NULLP;
756    }
757
758    /* Send msg to MAC */
759    ret = sendDlAllocToMac(&dlSchedInfo, schInst);
760    if(ret != ROK)
761    {
762       DU_LOG("\nERROR  -->  SCH : Sending DL Broadcast allocation from SCH to MAC failed");
763       return (ret);
764    }
765
766    /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */
767    node = cmLListFirst(&schCb[schInst].statistics.activeKpiList.dlTotPrbUseList);
768    while(node)
769    {
770       dlTotalPrbUsage = (TotalPrbUsage *)node->node;
771       if(dlTotalPrbUsage)
772       {
773          dlTotalPrbUsage->numPrbUsedForTx += cell->schDlSlotInfo[slot]->prbAlloc.numPrbAlloc;
774          dlTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB;
775       }
776       node = node->next;
777    }
778    
779    /* Re-initialize DL slot */
780    schInitDlSlot(cell->schDlSlotInfo[slot]);
781
782    /* Send UL Resource allocation to MAC */
783    schUlResAlloc(cell, schInst);
784
785 #ifdef NR_DRX 
786    schHandleExpiryDrxTimer(cell);
787 #endif   
788
789    return ret;
790 }
791
792 /**********************************************************************
793   End of file
794  **********************************************************************/
795
796