Merge "[Epic-ID: ODUHIGH-517][Task-ID: ODUHIGH-540][SubTask-Id: ODUHIGH-549] Multi...
[o-du/l2.git] / src / 5gnrsch / sch_fcfs.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 scheduling based on First Come First Serve
26           algorithm
27
28 File:     sch_fcfs.c
29
30  **********************************************************************/
31
32 /** @file sch_slot_ind.c
33   @brief This module processes slot indications
34  */
35 #include "common_def.h"
36 #include "tfu.h"
37 #include "lrg.h"
38 #include "tfu.x"
39 #include "lrg.x"
40 #include "du_log.h"
41 #include "du_app_mac_inf.h"
42 #include "mac_sch_interface.h"
43 #include "sch.h"
44 #include "sch_tmr.h"
45 #include "sch_utils.h"
46 #include "sch_fcfs.h"
47 #ifdef NR_DRX 
48 #include "sch_drx.h"
49 #endif
50
51 /*******************************************************************
52  *
53  * @brief Function to handle Cell configuration request
54  *
55  * @details
56  *
57  *    Function : schFcfsCellCfgReq
58  *
59  *    Functionality: This function configures cell paremeters
60  *       required for FCFS scheduling
61  *
62  * @params[in] SchCellCb *cellCb, Cell control block
63  * @return ROK
64  *         RFAILED
65  *
66  * ****************************************************************/
67 uint8_t schFcfsCellCfgReq(SchCellCb *cellCb)
68 {
69    SchFcfsCellCb *fcfsCellCb = NULLP;
70    
71    SCH_ALLOC(fcfsCellCb, sizeof(SchFcfsCellCb));
72    if(!fcfsCellCb)
73    {
74       DU_LOG("\nERROR  -->  SCH: Memory allocation failed in schFcfsCellCfgReq");
75       return RFAILED;
76    }
77    cmLListInit(&fcfsCellCb->ueToBeScheduled);
78    cellCb->schSpcCell = (void *)fcfsCellCb;
79    return ROK;
80 }
81
82 /*******************************************************************
83  *
84  * @brief Function to handle Cell configuration request
85  *
86  * @details
87  *
88  *    Function : schFcfsCellDelReq
89  *
90  *    Functionality: This function deletes/frees cell params
91  *       specific to FCFS scheduling
92  *
93  * @params[in] Pointer to Cell control block
94  * @return void
95  *
96  * ****************************************************************/
97 void schFcfsCellDelReq(SchCellCb *cellCb)
98 {
99    SchFcfsCellCb *fcfsCellCb = NULLP;
100    CmLList *node=NULL, *next=NULL;
101
102    fcfsCellCb = (SchFcfsCellCb *)cellCb->schSpcCell;
103    /* Remove all UE from ueToBeScheduled list and deallocate */
104    node = fcfsCellCb->ueToBeScheduled.first;
105    while(node)
106    {
107       next = node->next;
108       SCH_FREE(node->node, sizeof(uint8_t));
109       cmLListDelFrm(&fcfsCellCb->ueToBeScheduled, node);
110       SCH_FREE(node, sizeof(CmLList));
111       node = next;
112    }
113    SCH_FREE(fcfsCellCb, sizeof(SchFcfsCellCb));
114    cellCb->schSpcCell = NULLP;
115 }
116
117 /*******************************************************************
118  *
119  * @brief Function to handle UE configuration request
120  *
121  * @details
122  *
123  *    Function : SchFcfsAddUeConfigReq
124  *
125  *    Functionality: Adds/Configures UE parameters required for
126  *       FCFS scheduling
127  *
128  * @params[in] Pointer to UE control block
129  * @return ROK
130  *         RFAILED
131  *
132  * ****************************************************************/
133 uint8_t SchFcfsAddUeConfigReq(SchUeCb *ueCb)
134 {
135    SchFcfsUeCb *ueFcfsCb;
136
137    SCH_ALLOC(ueFcfsCb, sizeof(SchFcfsHqCb));
138    if(!ueFcfsCb)
139    {
140       DU_LOG("\nERROR  -->  SCH: Memory allocation failed in SchFcfsAddUeConfigReq");
141       return RFAILED;
142    }
143    
144    cmLListInit(&ueFcfsCb->hqRetxCb.ulRetxHqList);
145    cmLListInit(&ueFcfsCb->hqRetxCb.dlRetxHqList);
146    ueCb->schSpcUeCb = (void *)ueFcfsCb;
147    
148    return ROK;
149 }
150
151 /*******************************************************************
152  *
153  * @brief Handles UE reconfiguration request
154  *
155  * @details
156  *
157  *    Function : SchFcfsModUeConfigReq
158  *
159  *    Functionality: 
160  *
161  * @params[in] Pointer to UE control block
162  * @return void
163  *
164  * ****************************************************************/
165 void SchFcfsModUeConfigReq(SchUeCb *ueCb)
166 {
167    /*TBD: No action required for FCFS*/
168    return;
169 }
170
171 /*******************************************************************
172  *
173  * @brief Handles UE Delete Request
174  *
175  * @details
176  *
177  *    Function : SchFcfsUeDeleteReq 
178  *
179  *    Functionality: Deletes/Frees UE parameters specific to 
180  *       FCFS scheduling
181  *
182  * @params[in] Pointer to UE control block
183  * @return void
184  *
185  * ****************************************************************/
186 void SchFcfsUeDeleteReq(SchUeCb *ueCb)
187 {
188    SchFcfsCellCb *fcfsCellCb = NULLP;
189    SchFcfsUeCb *ueFcfsCb = NULLP;
190    CmLList *node=NULL, *next=NULL;
191    uint8_t ueId = 0;
192
193    fcfsCellCb = (SchFcfsCellCb *)ueCb->cellCb->schSpcCell;
194    /* Remove all UE from ueToBeScheduled list and deallocate */
195    node = fcfsCellCb->ueToBeScheduled.first;
196    while(node)
197    {
198       next = node->next;
199       ueId = *(uint8_t *)node->node;
200       if(ueId == ueCb->ueId)
201       {
202         SCH_FREE(node->node, sizeof(uint8_t));
203         cmLListDelFrm(&fcfsCellCb->ueToBeScheduled, node);
204         SCH_FREE(node, sizeof(CmLList));
205         break;
206       }
207       node = next;
208    }
209    
210    ueFcfsCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
211    cmLListDeleteLList(&ueFcfsCb->hqRetxCb.ulRetxHqList);
212    cmLListDeleteLList(&ueFcfsCb->hqRetxCb.dlRetxHqList);
213
214    SCH_FREE(ueFcfsCb, sizeof(SchFcfsUeCb));
215    ueCb->schSpcUeCb = NULLP;
216    return;
217 }
218
219 /*******************************************************************
220  *
221  * @brief Intializes HARQ Process control block
222  *
223  * @details
224  *
225  *    Function : schFcfsInitDlHqProcCb
226  *
227  *    Functionality: Intitialized parameters of HARQ process control
228  *       block specific to FCFS scheduling in Downlink
229  *
230  * @params[in] Pointer to Downlink HARQ Process control block
231  * @return ROK
232  *         RFAILED
233  *
234  * ****************************************************************/
235 uint8_t schFcfsInitDlHqProcCb(SchDlHqProcCb *hqP)
236 {
237    SchFcfsHqProcCb *fcfsHqP;
238
239    SCH_ALLOC(fcfsHqP, sizeof(SchFcfsHqProcCb));
240    if(!fcfsHqP)
241    {
242       DU_LOG("\nERROR  -->  SCH: Memory allocation failed in schFcfsInitDlHqProcCb");
243       return RFAILED;
244    }
245
246    cmLListInit(&fcfsHqP->lcCb.dedLcList);
247    cmLListInit(&fcfsHqP->lcCb.defLcList);
248    hqP->schSpcDlHqProcCb = (void *)fcfsHqP;
249
250    return ROK;
251 }
252
253 /*******************************************************************
254  *
255  * @brief Handles HARQ Process delete request
256  *
257  * @details 
258  *
259  *    Function : schFcfsDeleteDlHqProcCb
260  *
261  *    Functionality: Deletes HARQ Process parameters specific to 
262  *       FCFS scheduling in Downlink
263  *
264  * @params[in] Pointer to Downlink HARQ Process control block
265  * @return void
266  *
267  * ****************************************************************/
268 void schFcfsDeleteDlHqProcCb(SchDlHqProcCb *hqP)
269 {
270    SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcDlHqProcCb;
271    cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
272    cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
273    SCH_FREE(fcfsHqP, sizeof(SchFcfsHqProcCb));
274    hqP->schSpcDlHqProcCb = NULLP;
275 }
276
277 /*******************************************************************
278  *
279  * @brief Intializes HARQ Process control block
280  *
281  * @details
282  *
283  *    Function : schFcfsInitUlHqProcCb
284  *
285  *    Functionality: Intitialized parameters of HARQ process control
286  *       block specific to FCFS scheduling in Uplink
287  *
288  * @params[in] Pointer to Uplink HARQ Process control block
289  * @return ROK
290  *         RFAILED
291  *
292  * ****************************************************************/
293 uint8_t schFcfsInitUlHqProcCb(SchUlHqProcCb *hqP)
294 {
295    SchFcfsHqProcCb *fcfsHqP;
296
297    SCH_ALLOC(fcfsHqP, sizeof(SchFcfsHqProcCb));
298    if(!fcfsHqP)
299    {
300       DU_LOG("\nERROR  -->  SCH: Memory allocation failed in schFcfsInitUlHqProcCb");
301       return RFAILED;
302    }
303    cmLListInit(&fcfsHqP->lcCb.dedLcList);
304    cmLListInit(&fcfsHqP->lcCb.defLcList);
305    hqP->schSpcUlHqProcCb = (void *)fcfsHqP;
306  
307    return ROK;
308 }
309
310 /*******************************************************************
311  *
312  * @brief Handled Deletion of HARQ Process control block
313  *
314  * @details
315  *
316  *    Function : schFcfsDeleteUlHqProcCb
317  *
318  *    Functionality: Deletes HARQ Process parameters specific to 
319  *       FCFS scheduling in Uplink
320  *
321  * @params[in] Pointer to Uplink HARQ Process Control block
322  * @return void
323  *
324  * ****************************************************************/
325 void schFcfsDeleteUlHqProcCb(SchUlHqProcCb *hqP)
326 {
327    SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcUlHqProcCb;
328    cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
329    cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
330    SCH_FREE(fcfsHqP, sizeof(SchFcfsHqProcCb));
331    hqP->schSpcUlHqProcCb = NULLP;
332 }
333
334 /*******************************************************************
335  *
336  * @brief Handles freeing of HARQ Process
337  *
338  * @details
339  *
340  *    Function : schFcfsFreeDlHqProcCb
341  *
342  *    Functionality: Frees HARQ Process parameters specific to 
343  *       FCFS scheduling in Downlink when HARQ process becomes free
344  *
345  * @params[in] Pointer to HARQ process control block
346  * @return void
347  *
348  * ****************************************************************/
349 void schFcfsFreeDlHqProcCb(SchDlHqProcCb *hqP)
350 {
351    SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcDlHqProcCb;
352
353    cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
354    cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
355 }
356
357 /*******************************************************************
358  *
359  * @brief Handles freeing of HARQ Process
360  *
361  * @details
362  *
363  *    Function : schFcfsFreeUlHqProcCb
364  *
365  *    Functionality: Frees HARQ Process parameters specific to 
366  *       FCFS scheduling in Uplink when HARQ process becomes free
367  *
368  * @params[in] Pointer to HARQ process control block
369  * @return void
370  *
371  * ****************************************************************/
372 void schFcfsFreeUlHqProcCb(SchUlHqProcCb *hqP)
373 {
374    SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcUlHqProcCb;
375
376    cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
377    cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
378 }
379
380 /*******************************************************************
381  *
382  * @brief Adds HARQ process to retransmission list
383  *
384  * @details
385  *
386  *    Function : schFcfsAddToDlHqRetxList
387  *
388  *    Functionality: Adds HARQ process to retransmission list
389  *
390  * @params[in] Pointer to Downlink HARQ Process 
391  * @return void
392  *
393  * ****************************************************************/
394 void schFcfsAddToDlHqRetxList(SchDlHqProcCb *hqP)
395 {
396    SchFcfsUeCb *fcfsUeCb;
397
398    fcfsUeCb = (SchFcfsUeCb *)hqP->hqEnt->ue->schSpcUeCb;
399    cmLListAdd2Tail(&(fcfsUeCb->hqRetxCb.dlRetxHqList),&hqP->dlHqProcLink);  
400 #ifdef NR_DRX
401    if(hqP->hqEnt->ue->ueDrxInfoPres == true)
402    {
403       schDrxStrtDlHqRttTmr(hqP);
404    }
405    else
406 #endif
407    {
408       schFcfsAddUeToSchedule(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
409    }
410 }
411
412 /*******************************************************************
413  *
414  * @brief Adds HARQ process to retransmission list
415  *
416  * @details
417  *
418  *    Function : schFcfsAddToUlHqRetxList
419  *
420  *    Functionality: Adds HARQ process to retransmission list
421  *
422  * @params[in] Pointer to Uplink HARQ Process 
423  * @return void
424  *
425  * ****************************************************************/
426 void schFcfsAddToUlHqRetxList(SchUlHqProcCb *hqP)
427 {
428    SchFcfsUeCb *fcfsUeCb;
429
430    fcfsUeCb = (SchFcfsUeCb *)hqP->hqEnt->ue->schSpcUeCb;
431    cmLListAdd2Tail(&(fcfsUeCb->hqRetxCb.ulRetxHqList),&hqP->ulHqProcLink);  
432 #ifdef NR_DRX
433    if(hqP->hqEnt->ue->ueDrxInfoPres == true)
434    {
435       schDrxStrtUlHqRttTmr(hqP);
436    }
437    else
438 #endif
439    {
440       schFcfsAddUeToSchedule(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
441    }   
442 }
443
444 /*******************************************************************
445  *
446  * @brief Add UE to ueToBeScheduled List
447  *
448  * @details
449  *
450  *    Function : schFcfsAddUeToSchedule
451  *
452  *    Functionality:
453  *      Search if UE entry present in the list
454  *      If yes, return.
455  *      If no, add UE to the list
456  *
457  * @params[in] Cell control block
458  *             Ue Id to be added
459  *
460  * @return ROK     - success
461  *         RFAILED - failure
462  *
463  * ****************************************************************/
464 uint8_t schFcfsAddUeToSchedule(SchCellCb *cellCb, uint16_t ueIdToAdd)
465 {
466    SchFcfsCellCb *fcfsCellCb = NULLP;
467    uint8_t *ueId;
468    CmLList *node;
469
470    fcfsCellCb = (SchFcfsCellCb *)cellCb->schSpcCell;
471    /* Search if UE entry is already present in ueToBeScheduled list.
472     * If yes, another entry for same UE not needed. Hence, return */
473    node = fcfsCellCb->ueToBeScheduled.first;
474    while(node)
475    {
476       ueId = (uint8_t *)node->node;
477       if(*ueId == ueIdToAdd)
478          return ROK;
479       node = node->next;
480    }
481
482    /* If UE entry not present already, add UE to the end of ueToBeScheduled list */
483    SCH_ALLOC(ueId, sizeof(uint8_t));
484    if(!ueId)
485    {
486       DU_LOG("\nERROR  -->  SCH : Memory allocation failure in schFcfsAddUeToSchedule");
487       return RFAILED;
488    }
489    *ueId = ueIdToAdd;
490    if(addNodeToLList(&fcfsCellCb->ueToBeScheduled, ueId, NULLP) != ROK)
491    {
492       DU_LOG("\nERROR  --> SCH : Failed to add ueId [%d] to cell->ueToBeScheduled list", *ueId);
493       return RFAILED;
494    }
495    return ROK;
496 }
497
498 /*******************************************************************
499  *
500  * @brief Handled CRC Indication
501  *
502  * @details
503  *
504  *    Function : schFcfsProcessCrcInd
505  *
506  *    Functionality: Processes CRC Indication as required for FCFS
507  *       scheduling
508  *
509  * @params[in] Pointer to Cell control block
510  *             UE Id
511  * @return void
512  *
513  * ****************************************************************/
514 void schFcfsProcessCrcInd(SchCellCb *cellCb, uint16_t ueId)
515 {
516    schFcfsAddUeToSchedule(cellCb, ueId);   
517 }
518
519 /*******************************************************************
520  *
521  * @brief Processes Buffer Occupancy report from RLC
522  *
523  * @details
524  *
525  *    Function : schFcfsDlRlcBoInfo
526  *
527  *    Functionality: Process buffer occupany report 
528  *
529  * @params[in]
530  * @return
531  *
532  * ****************************************************************/
533 void schFcfsDlRlcBoInfo(SchCellCb *cellCb, uint16_t ueId)
534 {
535    schFcfsAddUeToSchedule(cellCb, ueId);   
536 }
537
538 /*******************************************************************
539  *
540  * @brief Processes BSR request
541  *
542  * @details
543  *
544  *    Function : schFcfsBsr
545  *
546  *    Functionality: Processes BSR as per FCFS scheduling
547  *
548  * @params[in] Pointer to Cell 
549  *             UE ID
550  * @return void
551  *
552  * ****************************************************************/
553 void schFcfsBsr(SchCellCb *cellCb, uint16_t ueId)
554 {
555    schFcfsAddUeToSchedule(cellCb, ueId);   
556 }
557
558 /*******************************************************************
559  *
560  * @brief Processed UCI Indication
561  *
562  * @details
563  *
564  *    Function : schFcfsSrUciInd
565  *
566  *    Functionality: Processing of UCI indication specific to 
567  *       FCFS scheduling
568  *
569  * @params[in] Pointer to Cell
570  *             UE Id
571  * @return void
572  *
573  * ****************************************************************/
574 void schFcfsSrUciInd(SchCellCb *cellCb, uint16_t ueId)
575 {
576    schFcfsAddUeToSchedule(cellCb, ueId);   
577 }
578
579 /*******************************************************************
580  *
581  * @brief Processing of RACH Indication
582  *
583  * @details
584  *
585  *    Function : schFcfsProcessRachInd
586  *
587  *    Functionality: Processing of RACH Indication specific to 
588  *       FCFS scheduling
589  *
590  * @params[in] Pointer to Cell Cb
591  *             UE Id
592  * @return void
593  *
594  * ****************************************************************/
595 void schFcfsProcessRachInd(SchCellCb *cellCb, uint16_t ueId)
596 {
597    schFcfsAddUeToSchedule(cellCb, ueId);   
598 }
599
600 /*******************************************************************
601  *
602  * @brief Processing of DL HARQ Indication
603  *
604  * @details
605  *
606  *    Function : SchFcfsDlHarqInd
607  *
608  *    Functionality:
609  *
610  * @params[in] 
611  * @return void
612  *
613  * ****************************************************************/
614 void SchFcfsDlHarqInd()
615 {
616    return;
617 }
618
619 /*******************************************************************
620  *
621  * @brief Processing of Paging indication
622  *
623  * @details
624  *
625  *    Function : schFcfsPagingInd
626  *
627  *    Functionality:
628  *
629  * @params[in]
630  * @return void
631  *
632  * ****************************************************************/
633 void schFcfsPagingInd()
634 {
635    return;
636 }
637
638 /*******************************************************************
639  *
640  * @brief Processing of RACH Resource Request
641  *
642  * @details
643  *
644  *    Function : schFcfsRachRsrcReq
645  *
646  *    Functionality:
647  *
648  * @params[in]
649  * @return void
650  *
651  * ****************************************************************/
652 void schFcfsRachRsrcReq()
653 {
654    return;
655 }
656
657 /*******************************************************************
658  *
659  * @brief Processing of RACH Resource Release
660  *
661  * @details
662  *
663  *    Function : schFcfsRachRsrcRel
664  *
665  *    Functionality:
666  *
667  * @params[in]
668  * @return void
669  *
670  * ****************************************************************/
671 void schFcfsRachRsrcRel()
672 {
673    return;
674 }
675
676 /*******************************************************************
677  *
678  * @brief Remove entry from HARQ retransmission list
679  *
680  * @details
681  *
682  *    Function : schFcfsRemoveFrmDlHqRetxList
683  *
684  *    Functionality: Remove entry from HARQ retransmission list
685  *
686  * @params[in] Pointer to UE
687  *             Node to be deleted
688  * @return void
689  *
690  * ****************************************************************/
691 void schFcfsRemoveFrmDlHqRetxList(SchUeCb *ueCb, CmLList *node)
692 {
693    SchFcfsUeCb *fcfsUeCb;
694
695    fcfsUeCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
696    cmLListDelFrm(&fcfsUeCb->hqRetxCb.dlRetxHqList, node);
697 }
698
699 /*******************************************************************
700  *
701  * @brief Remove entry from HARQ retransmission list
702  *
703  * @details
704  *
705  *    Function : schFcfsRemoveFrmUlHqRetxList
706  *
707  *    Functionality: Remove entry from HARQ retransmission list
708  *
709  * @params[in] Pointer to UE
710  *             Node to be deleted
711  * @return void
712  *
713  * ****************************************************************/
714 void schFcfsRemoveFrmUlHqRetxList(SchUeCb *ueCb, CmLList *node)
715 {
716    SchFcfsUeCb *fcfsUeCb;
717
718    fcfsUeCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
719    cmLListDelFrm(&fcfsUeCb->hqRetxCb.ulRetxHqList, node);
720 }
721
722 /*******************************************************************
723  *
724  * @brief Remove UE from Scheduling List
725  *
726  * @details
727  *
728  *    Function : schFcfsRemoveUeFrmScheduleLst
729  *
730  *    Functionality: Remove UE from Scheduling List
731  *
732  * @params[in] Pointer to Cell
733  *             Node to be removed
734  * @return void
735  *
736  * ****************************************************************/
737 void schFcfsRemoveUeFrmScheduleLst(SchCellCb *cell, CmLList *node)
738 {
739    SchFcfsCellCb *fcfsCell;
740
741    fcfsCell = (SchFcfsCellCb *)cell->schSpcCell;
742    SCH_FREE(node->node, sizeof(uint8_t));
743    deleteNodeFromLList(&fcfsCell->ueToBeScheduled, node);
744 }
745
746 /*******************************************************************
747  *
748  * @brief  Handler to calculate TBS size for BSR requested
749  *
750  * @details
751  *
752  *    Function :  schFcfsCalculateUlTbs
753  *
754  *    Functionality: Function will note the required TBS for each LCGIDX and use
755  *    the Priority LCG List and RRM policy to allocate the TBS size
756  *
757  * @params [in] ueCb (Pointer to UE CB)
758  *         [in] puschTime (Time slot where PUSCH will be sent)
759  *         [in] symbLen (No of Symbols used for PUSCH transmission)
760  *         [out] startPrb(Pointer to startPRB which will be calculated while
761  *         finding the best Free Block)
762  *         [out] totTBS(Pointer to total TBS size)
763  *         [in] isRetx (to indicate retransmission)
764  *         [in] hqP (UL Harq process pointer)
765  *
766  * @return uint8_t : ROK > Scheduling of UL grant is successful
767  *                   RFAILED > vice versa
768  *
769  * ****************************************************************/
770 uint8_t schFcfsCalculateUlTbs(SchUeCb *ueCb, SlotTimingInfo puschTime, uint8_t symbLen,\
771                           uint16_t *startPrb, uint32_t *totTBS, bool isRetx, SchUlHqProcCb *hqP, SchFcfsHqProcCb *fcfsHqP)
772 {
773    uint16_t mcsIdx = 0;
774    CmLListCp *lcLL = NULLP;
775    uint16_t lcgIdx = 0, lcId =0, maxFreePRB = 0;
776    uint16_t rsvdDedicatedPRB;
777    *startPrb = 0;
778    *totTBS = 0;
779
780    /* check for BSR */
781    for(lcgIdx=0; lcgIdx<MAX_NUM_LOGICAL_CHANNEL_GROUPS; lcgIdx++)
782    {
783       if(ueCb->bsrInfo[lcgIdx].dataVol == 0)
784       {
785          continue;
786       }
787
788       /*TODO: lcgIdx and LCID has been implemented as one to one mapping.
789        * Need to check the mapping to figure out the LCID and lcgIdx once L2
790        * spec specifies any logic*/
791       lcId = lcgIdx;
792       if(ueCb->ulInfo.ulLcCtxt[lcId].isDedicated)
793       {
794          lcLL = &(fcfsHqP->lcCb.dedLcList);
795          rsvdDedicatedPRB = ueCb->ulInfo.ulLcCtxt[lcId].rsvdDedicatedPRB;
796       }
797       else
798       {
799          lcLL = &(fcfsHqP->lcCb.defLcList);
800       }
801
802       /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
803       if(updateLcListReqPRB(lcLL, lcId, ueCb->bsrInfo[lcgIdx].dataVol) != ROK)
804       {
805          DU_LOG("\nERROR  --> SCH: LcgId:%d updation failed",lcId);         
806          return RFAILED;
807       }
808    }
809
810    if ((fcfsHqP->lcCb.defLcList.count == 0) && (fcfsHqP->lcCb.dedLcList.count == 0))
811    {
812       if( (ueCb->srRcvd) || (isRetx) )
813       {
814          *startPrb = MAX_NUM_RB;
815          *totTBS = schCalcTbSize(UL_GRANT_SIZE);
816       }
817       /*Returning true when NO Grant is there for UE as this is not scheduling
818        * error*/      
819       return ROK;
820    }
821
822    maxFreePRB = searchLargestFreeBlock(ueCb->cellCb, puschTime, startPrb, DIR_UL);
823
824    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
825     * the list based on RRM policy*/
826
827    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
828     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
829    if(maxFreePRB != 0)
830    {
831       mcsIdx = ueCb->ueCfg.ulModInfo.mcsIndex;
832       if((fcfsHqP->lcCb.dedLcList.count == 0) || ((maxFreePRB < rsvdDedicatedPRB)))
833       {
834          fcfsHqP->lcCb.sharedNumPrb = maxFreePRB;
835          DU_LOG("\nDEBUG  -->  SCH : UL Only Default Slice is scheduled, sharedPRB Count:%d",\
836                fcfsHqP->lcCb.sharedNumPrb);
837
838          /*PRB Alloc for Default LCs*/
839          prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.defLcList), FALSE, mcsIdx, symbLen,\
840                &(fcfsHqP->lcCb.sharedNumPrb), NULLP, NULLP,&(ueCb->srRcvd));
841       }
842       else
843       {
844          fcfsHqP->lcCb.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
845
846          /*PRB Alloc for Dedicated LCs*/
847          prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.dedLcList), TRUE, mcsIdx, symbLen,\
848                &(fcfsHqP->lcCb.sharedNumPrb), &(rsvdDedicatedPRB),\
849                NULLP, &(ueCb->srRcvd));
850
851          /*PRB Alloc for Default LCs*/
852          prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.defLcList), FALSE, mcsIdx, symbLen, \
853                &(fcfsHqP->lcCb.sharedNumPrb), &(rsvdDedicatedPRB),\
854                NULLP,&(ueCb->srRcvd));
855       }
856    }
857    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
858     * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/ 
859    if(fcfsHqP->lcCb.dedLcList.count != 0)
860       updateGrantSizeForBoRpt(&(fcfsHqP->lcCb.dedLcList), NULLP, ueCb->bsrInfo, totTBS);
861
862    updateGrantSizeForBoRpt(&(fcfsHqP->lcCb.defLcList), NULLP, ueCb->bsrInfo, totTBS);
863
864    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
865    if (*totTBS == 0)
866    {
867       if(maxFreePRB == 0)
868       {
869          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
870       }
871       else
872       {
873          /*Schedule the LC for next slot*/
874          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
875       }      
876       return RFAILED;
877    }   
878    return ROK;
879 }
880
881 /*******************************************************************
882  *
883  * @brief Grants resources to LC in uplink
884  *
885  * @details
886  *
887  *    Function : schProcessSrOrBsrReq
888  *
889  *    Functionality:
890  *       Grants resources to LC in uplink
891  *
892  * @params[in] PDCCH Time
893  *             PUSCH Time
894  *             Start Symbol
895  *             Number of symbols
896  *             Is retransmission
897  *             HARQ process
898  * @return ROK
899  *         RFAILED
900  *
901  *******************************************************************/
902 uint8_t schFcfsScheduleUlLc(SlotTimingInfo dciTime, SlotTimingInfo puschTime, uint8_t startSymb , uint8_t symbLen, bool isRetx, SchUlHqProcCb **hqP)
903 {
904    SchCellCb *cell;
905    SchFcfsHqProcCb *fcfsHqProcCb;
906    uint8_t ret = RFAILED;
907    uint16_t startPrb = 0;
908    uint32_t totDataReq = 0; /* in bytes */
909    SchUeCb *ueCb;
910    SchPuschInfo *puschInfo;
911    DciInfo  *dciInfo = NULLP;
912
913    cell = (*hqP)->hqEnt->cell;
914    ueCb = (*hqP)->hqEnt->ue;
915    fcfsHqProcCb = (SchFcfsHqProcCb *)(*hqP)->schSpcUlHqProcCb;
916    ret = schFcfsCalculateUlTbs(ueCb, puschTime, symbLen, &startPrb, &totDataReq, isRetx, *hqP, fcfsHqProcCb);
917
918    if(totDataReq > 0 && ret == ROK)
919    {
920       SCH_ALLOC(dciInfo, sizeof(DciInfo));
921       if(!dciInfo)
922       {
923          DU_LOG("\nERROR  -->  SCH : Memory Allocation failed for dciInfo alloc");
924          if(isRetx != TRUE)
925          {
926             if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
927                updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, RFAILED);
928
929             updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, RFAILED);
930          }
931          return RFAILED;
932       }
933       cell->schDlSlotInfo[dciTime.slot]->ulGrant = dciInfo;
934       memset(dciInfo,0,sizeof(DciInfo));
935
936       /* Update PUSCH allocation */
937       if(schFillPuschAlloc(ueCb, puschTime, totDataReq, startSymb, symbLen, startPrb, isRetx, *hqP) == ROK)
938       {
939          if(cell->schUlSlotInfo[puschTime.slot]->schPuschInfo)
940          {
941             puschInfo = cell->schUlSlotInfo[puschTime.slot]->schPuschInfo;
942             if(puschInfo != NULLP)
943             {
944                /* Fill DCI for UL grant */
945                schFillUlDci(ueCb, puschInfo, dciInfo, isRetx, *hqP);
946                ueCb->srRcvd = false;
947                ueCb->bsrRcvd = false;
948                cell->schUlSlotInfo[puschTime.slot]->puschUe = ueCb->ueId;
949                if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
950                   updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, ROK);
951                updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, ROK);
952                cmLListAdd2Tail(&(ueCb->hqUlmap[puschTime.slot]->hqList), &(*hqP)->ulSlotLnk);                  
953                return ROK;
954             }
955          }
956       }
957       if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
958          updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, RFAILED);
959       updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, RFAILED);
960    }
961    return ROK;
962 }
963
964 /*******************************************************************
965  *
966  * @brief Grants resources to LC in downlink 
967  *
968  * @details
969  *
970  *    Function : schFcfsScheduleDlLc 
971  *
972  *    Functionality: Grants resources to LC in uplink
973  *
974  * @params[in] PDCCH Time
975  *
976  * @return ROK
977  *         RFAILED
978  *
979  * ****************************************************************/
980 uint32_t schFcfsScheduleDlLc(SlotTimingInfo pdcchTime, SlotTimingInfo pdschTime, uint8_t pdschNumSymbols, \
981                                uint16_t *startPrb, bool isRetx, SchDlHqProcCb **hqP)
982 {
983    SchFcfsHqProcCb *fcfsHqProcCb;
984    SchUeCb *ueCb;
985    uint8_t lcIdx = 0;
986    uint16_t maxFreePRB = 0;
987    uint16_t mcsIdx = 0;
988    uint32_t accumalatedSize = 0;
989    CmLListCp *lcLL = NULLP;
990    uint16_t rsvdDedicatedPRB = 0;
991    DlMsgSchInfo *dciSlotAlloc;
992
993    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
994     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
995     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
996     * else if only Default list is present then first node in this List will add this overhead len*/
997    bool isTxPayloadLenAdded = FALSE;
998
999    ueCb = (*hqP)->hqEnt->ue;
1000    dciSlotAlloc = (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1];
1001    fcfsHqProcCb = (SchFcfsHqProcCb *)((*hqP)->schSpcDlHqProcCb);
1002
1003    if (isRetx == FALSE)
1004    {
1005       /*Re-Initalization per UE*/
1006       /* scheduled LC data fill */
1007       dciSlotAlloc->transportBlock[0].numLc = 0;
1008       isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
1009       accumalatedSize = 0;
1010
1011       for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
1012       {
1013          if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
1014          {
1015             /*Check the LC is Dedicated or default and accordingly LCList will
1016             * be used*/
1017             if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
1018             {
1019                lcLL = &(fcfsHqProcCb->lcCb.dedLcList);
1020                rsvdDedicatedPRB = ueCb->dlInfo.dlLcCtxt[lcIdx].rsvdDedicatedPRB;
1021             }
1022             else
1023             {
1024                lcLL = &(fcfsHqProcCb->lcCb.defLcList);
1025             }
1026
1027             /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
1028             if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
1029                      (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
1030             {
1031                DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
1032                /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
1033                if(!dciSlotAlloc->dlMsgPdschCfg)
1034                {
1035                   SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1036                   (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
1037                }
1038                return accumalatedSize;
1039             }
1040          }
1041       }//End of for loop
1042
1043       if ((fcfsHqProcCb->lcCb.defLcList.count == 0) && (fcfsHqProcCb->lcCb.dedLcList.count == 0))
1044       {
1045          DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
1046          UNSET_ONE_BIT((*hqP)->hqEnt->ue->ueId, (*hqP)->hqEnt->cell->boIndBitMap);
1047
1048          /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
1049          if(!dciSlotAlloc->dlMsgPdschCfg)
1050          {
1051             SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1052             (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
1053          }
1054          /*TRUE because this UE has nothing to be scheduled*/
1055          return accumalatedSize;
1056       }
1057    }
1058
1059    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
1060    maxFreePRB = searchLargestFreeBlock((*hqP)->hqEnt->cell, pdschTime, startPrb, DIR_DL);
1061
1062    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
1063     * the list based on RRM policy*/
1064
1065    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
1066     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
1067    if(isRetx == FALSE)
1068    {
1069       if(maxFreePRB != 0)
1070       {
1071          mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
1072
1073          if((fcfsHqProcCb->lcCb.dedLcList.count == NULLP) || ((maxFreePRB < rsvdDedicatedPRB)))
1074          { 
1075             fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB;
1076             DU_LOG("\nDEBUG  -->  SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
1077                   fcfsHqProcCb->lcCb.sharedNumPrb);
1078
1079             /*PRB Alloc for Default LCs*/
1080             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
1081                   &(fcfsHqProcCb->lcCb.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
1082          }
1083          else
1084          {
1085             fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
1086             /*PRB Alloc for Dedicated LCs*/
1087             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
1088                   &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
1089
1090             /*PRB Alloc for Default LCs*/
1091             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
1092                   &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
1093          }
1094       }
1095    }
1096
1097    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
1098     * using allocated BO per LC and Update dlMsgAlloc BO report for MAC */
1099    if (isRetx == FALSE)
1100    {
1101       if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
1102          updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
1103
1104       updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
1105    }
1106    else
1107    {
1108       accumalatedSize = (*hqP)->tbInfo[0].tbSzReq;
1109    }
1110
1111    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
1112    if (!accumalatedSize)
1113    {
1114       if(maxFreePRB == 0)
1115       {
1116          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
1117       }
1118       else
1119       {
1120          /*Schedule the LC for next slot*/
1121          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
1122       }
1123       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
1124        * Allocation can be done in next slot*/
1125       accumalatedSize = 0;
1126    }
1127
1128    return accumalatedSize;
1129 }
1130
1131 /*******************************************************************
1132  *
1133  * @brief Scheduling of Slots in UL And DL 
1134  *
1135  * @details
1136  *
1137  *    Function : schFcfsScheduleSlot
1138  *
1139  *    Functionality: Scheduling of slots in UL and DL specific to 
1140  *       FCFS scheduling
1141  *
1142  * @params[in] Pointer to Cell
1143  *             Slot timing info
1144  *             Scheduler instance
1145  * @return void
1146  *
1147  * ****************************************************************/
1148 void schFcfsScheduleSlot(SchCellCb *cell, SlotTimingInfo *slotInd, Inst schInst)
1149 {
1150    SchFcfsCellCb  *fcfsCell;
1151    SchFcfsUeCb    *fcfsUeCb;
1152    SchDlHqProcCb  *hqP = NULLP;
1153    SchUlHqProcCb  *ulHqP = NULLP;
1154    CmLList        *pendingUeNode;
1155    CmLList        *node;
1156    uint8_t        ueId;
1157    bool           isRarPending = false, isRarScheduled = false;
1158    bool           isMsg4Pending = false, isMsg4Scheduled = false;
1159    bool           isDlMsgPending = false, isDlMsgScheduled = false;
1160    bool           isUlGrantPending = false, isUlGrantScheduled = false;
1161    bool           isNodeFreed = false;
1162
1163    fcfsCell = (SchFcfsCellCb *)cell->schSpcCell;
1164    
1165    /* Select first UE in the linked list to be scheduled next */
1166    pendingUeNode = fcfsCell->ueToBeScheduled.first;
1167    while(pendingUeNode)
1168    {
1169       if(pendingUeNode->node)
1170       {
1171          ueId = *(uint8_t *)(pendingUeNode->node);
1172          fcfsUeCb = (SchFcfsUeCb *)cell->ueCb[ueId-1].schSpcUeCb;
1173
1174          /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
1175           * PUSCH to receive MSG3 as per k0-k2 configuration*/
1176          if(cell->raReq[ueId-1] != NULLP)
1177          {
1178             isRarPending = true;
1179             isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
1180          }
1181
1182          /*MSG3 retransmisson*/
1183          if(cell->raCb[ueId-1].retxMsg3HqProc)
1184          {            
1185             schMsg3RetxSchedulingForUe(&(cell->raCb[ueId-1]));
1186          }
1187
1188          /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
1189           * PUCCH to receive UL msg as per k0-k1 configuration  */
1190          if (cell->ueCb[ueId-1].retxMsg4HqProc) //should work from dlmap later tbd
1191          {
1192             /* Retransmission of MSG4 */
1193             isMsg4Pending = true;
1194             if(schProcessMsg4Req(cell, *slotInd, ueId, TRUE, &cell->ueCb[ueId-1].retxMsg4HqProc) == ROK)
1195                isMsg4Scheduled = true;
1196          }
1197          else
1198          {
1199             /* First transmission of MSG4 */
1200             if(cell->raCb[ueId-1].msg4recvd)
1201             {
1202                isMsg4Pending = true;
1203                if(schProcessMsg4Req(cell, *slotInd, ueId, FALSE, &cell->ueCb[ueId-1].msg4HqProc) == ROK)
1204                   isMsg4Scheduled = true;
1205
1206                /* If MSG4 scheduling failed, free the newly assigned HARQ process */
1207                if(!isMsg4Scheduled)
1208                   schDlReleaseHqProcess(cell->ueCb[ueId-1].msg4HqProc);
1209             }
1210          }
1211
1212          if(isRarPending || isMsg4Pending)
1213          {
1214             /* If RAR or MSG is successfully scheduled then
1215              * remove UE from linked list since no pending msgs for this UE */
1216             if(isRarScheduled || isMsg4Scheduled)
1217             {
1218                schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
1219                isNodeFreed = true;
1220             }
1221             /* If RAR/MSG4 is pending but couldnt be scheduled then,
1222              * put this UE at the end of linked list to be scheduled later */
1223             else
1224             {
1225                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1226             }
1227          }
1228
1229 #ifdef NR_DRX 
1230          if((cell->ueCb[ueId-1].ueDrxInfoPres == true) && (cell->ueCb[ueId-1].drxUeCb.drxDlUeActiveStatus != true))
1231          {
1232             if(pendingUeNode->node)
1233             {
1234                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1235             }
1236          }
1237          else 
1238 #endif
1239          {
1240
1241             /* DL Data */
1242             node = NULLP;
1243             if(fcfsUeCb)
1244                node = fcfsUeCb->hqRetxCb.dlRetxHqList.first;
1245             if(node != NULLP)
1246             {
1247                /* DL Data ReTransmisson */
1248                isDlMsgPending = true;
1249                isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, TRUE, ((SchDlHqProcCb**) &(node->node)));
1250                if(isDlMsgScheduled)
1251                {
1252 #ifdef NR_DRX 
1253                   schDrxStopDlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchDlHqProcCb**) &(node->node)));
1254 #endif
1255                   schFcfsRemoveFrmDlHqRetxList(&cell->ueCb[ueId-1], node);
1256                }
1257             }
1258             else
1259             {
1260                /* DL Data new transmission */
1261                if((cell->boIndBitMap) & (1<<ueId))
1262                {
1263                   isDlMsgPending = true;               
1264                   isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, FALSE, &hqP);
1265
1266                   /* If DL scheduling failed, free the newly assigned HARQ process */
1267                   if(!isDlMsgScheduled)
1268                      schDlReleaseHqProcess(hqP);
1269                   else
1270                   {
1271 #ifdef NR_DRX
1272                      schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_DL + SCHED_DELTA);
1273 #endif
1274                   }
1275                }
1276             }
1277
1278             /* Scheduling of UL grant */
1279             node = NULLP;
1280             if(fcfsUeCb)
1281                node = fcfsUeCb->hqRetxCb.ulRetxHqList.first;
1282             if(node != NULLP)
1283             {
1284                /* UL Data ReTransmisson */
1285                isUlGrantPending = true;
1286                isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, TRUE, (SchUlHqProcCb**) &(node->node));
1287                if(isUlGrantScheduled)
1288                {
1289 #ifdef NR_DRX 
1290                   schDrxStopUlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchUlHqProcCb**) &(node->node)));
1291 #endif
1292                   schFcfsRemoveFrmUlHqRetxList(&cell->ueCb[ueId-1], node);
1293                }
1294             }
1295             else
1296             {
1297                /* UL Data new transmission */
1298                if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
1299                {
1300                   isUlGrantPending = true;
1301                   isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, FALSE, &ulHqP);
1302                   if(!isUlGrantScheduled)
1303                      schUlReleaseHqProcess(ulHqP, FALSE);
1304                   else
1305                   {
1306 #ifdef NR_DRX
1307                      schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_UL + SCHED_DELTA);
1308 #endif
1309                   }
1310                }
1311             }
1312
1313             if(!isUlGrantPending && !isDlMsgPending)
1314             {
1315                /* No action required */  
1316             }
1317             else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
1318             {
1319                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1320             }
1321             else
1322             {
1323                schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
1324                isNodeFreed = true;
1325             }
1326          }
1327       }
1328       if(cell->schDlSlotInfo[slotInd->slot]->prbAlloc.numPrbAlloc >= MAX_NUM_RB)
1329       {
1330         DU_LOG("\nINFO   -->  SCH: No PRB available to proceed with next UE");
1331         return;     
1332       }
1333       if(isNodeFreed == false)
1334       {
1335          pendingUeNode= pendingUeNode->next;
1336       }
1337       else
1338       {
1339         pendingUeNode = fcfsCell->ueToBeScheduled.first;
1340       }
1341    }
1342 }
1343
1344 /*******************************************************************
1345  *
1346  * @brief Initializes all function pointers to FCFS function handler
1347  *
1348  * @details
1349  *
1350  *    Function : schFcfsAllApisInit
1351  *
1352  *    Functionality: Initializes all function pointers to FCFS 
1353  *       function handler
1354  *
1355  * @params[in] Function pointer array
1356  * @return void
1357  *
1358  * ****************************************************************/
1359 void schFcfsAllApisInit(SchAllApis *allFcfsApi)
1360 {
1361     /* Interface API function pointers */
1362     allFcfsApi->SchCellCfgReq = schFcfsCellCfgReq;
1363     allFcfsApi->SchCellDeleteReq = schFcfsCellDelReq;
1364     allFcfsApi->SchAddUeConfigReq = SchFcfsAddUeConfigReq;
1365     allFcfsApi->SchModUeConfigReq = SchFcfsModUeConfigReq;
1366     allFcfsApi->SchUeDeleteReq = SchFcfsUeDeleteReq; 
1367     allFcfsApi->SchDlHarqInd = SchFcfsDlHarqInd; 
1368     allFcfsApi->SchCrcInd = schFcfsProcessCrcInd;
1369     allFcfsApi->SchRachInd = schFcfsProcessRachInd;
1370     allFcfsApi->SchPagingInd = schFcfsPagingInd;
1371     allFcfsApi->SchRachRsrcReq = schFcfsRachRsrcReq; 
1372     allFcfsApi->SchRachRsrcRel = schFcfsRachRsrcRel;
1373     allFcfsApi->SchDlRlcBoInfo = schFcfsDlRlcBoInfo;
1374     allFcfsApi->SchSrUciInd = schFcfsSrUciInd;
1375     allFcfsApi->SchBsr = schFcfsBsr;
1376
1377     /* Internal API function pointers */
1378     allFcfsApi->SchAddToDlHqRetxList = schFcfsAddToDlHqRetxList;
1379     allFcfsApi->SchAddToUlHqRetxList = schFcfsAddToUlHqRetxList;
1380     allFcfsApi->SchRemoveFrmDlHqRetxList = schFcfsRemoveFrmDlHqRetxList;
1381     allFcfsApi->SchRemoveFrmUlHqRetxList = schFcfsRemoveFrmUlHqRetxList;
1382     allFcfsApi->SchAddUeToSchedule = schFcfsAddUeToSchedule;
1383     allFcfsApi->SchRemoveUeFrmScheduleLst = schFcfsRemoveUeFrmScheduleLst;
1384     allFcfsApi->SchInitDlHqProcCb = schFcfsInitDlHqProcCb;
1385     allFcfsApi->SchInitUlHqProcCb = schFcfsInitUlHqProcCb;
1386     allFcfsApi->SchFreeDlHqProcCb = schFcfsFreeDlHqProcCb;
1387     allFcfsApi->SchFreeUlHqProcCb = schFcfsFreeUlHqProcCb;
1388     allFcfsApi->SchDeleteDlHqProcCb = schFcfsDeleteDlHqProcCb;
1389     allFcfsApi->SchDeleteUlHqProcCb = schFcfsDeleteUlHqProcCb;
1390     allFcfsApi->SchScheduleSlot = schFcfsScheduleSlot;
1391     allFcfsApi->SchScheduleDlLc = schFcfsScheduleDlLc;
1392     allFcfsApi->SchScheduleUlLc = schFcfsScheduleUlLc;
1393 }
1394 /**********************************************************************
1395     End of file
1396 **********************************************************************/
1397