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