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