Merge "[Epic-ID: ODUHIGH-556][Task-ID: ODUHIGH-570] UL Candidate Sel and Res Alloc...
[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 = NULLP;
910    SchPuschInfo *puschInfo = NULLP;
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[ueCb->ueId])
940          {
941             puschInfo = cell->schUlSlotInfo[puschTime.slot]->schPuschInfo[ueCb->ueId];
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                if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
949                   updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, ROK);
950                updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, ROK);
951                cmLListAdd2Tail(&(ueCb->hqUlmap[puschTime.slot]->hqList), &(*hqP)->ulSlotLnk);                  
952                return ROK;
953             }
954          }
955       }
956       if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
957          updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, RFAILED);
958       updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, RFAILED);
959    }
960    return ROK;
961 }
962
963 /*******************************************************************
964  *
965  * @brief Grants resources to LC in downlink 
966  *
967  * @details
968  *
969  *    Function : schFcfsScheduleDlLc 
970  *
971  *    Functionality: Grants resources to LC in uplink
972  *
973  * @params[in] PDCCH Time
974  *
975  * @return ROK
976  *         RFAILED
977  *
978  * ****************************************************************/
979 uint32_t schFcfsScheduleDlLc(SlotTimingInfo pdcchTime, SlotTimingInfo pdschTime, uint8_t pdschNumSymbols, \
980                                uint16_t *startPrb, bool isRetx, SchDlHqProcCb **hqP)
981 {
982    SchFcfsHqProcCb *fcfsHqProcCb;
983    SchUeCb *ueCb;
984    uint8_t lcIdx = 0;
985    uint16_t maxFreePRB = 0;
986    uint16_t mcsIdx = 0;
987    uint32_t accumalatedSize = 0;
988    CmLListCp *lcLL = NULLP;
989    uint16_t rsvdDedicatedPRB = 0;
990    DlMsgSchInfo *dciSlotAlloc;
991
992    /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
993     * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
994     * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
995     * else if only Default list is present then first node in this List will add this overhead len*/
996    bool isTxPayloadLenAdded = FALSE;
997
998    ueCb = (*hqP)->hqEnt->ue;
999    dciSlotAlloc = (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1];
1000    fcfsHqProcCb = (SchFcfsHqProcCb *)((*hqP)->schSpcDlHqProcCb);
1001
1002    if (isRetx == FALSE)
1003    {
1004       /*Re-Initalization per UE*/
1005       /* scheduled LC data fill */
1006       dciSlotAlloc->transportBlock[0].numLc = 0;
1007       isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
1008       accumalatedSize = 0;
1009
1010       for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
1011       {
1012          if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
1013          {
1014             /*Check the LC is Dedicated or default and accordingly LCList will
1015             * be used*/
1016             if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
1017             {
1018                lcLL = &(fcfsHqProcCb->lcCb.dedLcList);
1019                rsvdDedicatedPRB = ueCb->dlInfo.dlLcCtxt[lcIdx].rsvdDedicatedPRB;
1020             }
1021             else
1022             {
1023                lcLL = &(fcfsHqProcCb->lcCb.defLcList);
1024             }
1025
1026             /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
1027             if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
1028                      (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
1029             {
1030                DU_LOG("\nERROR  --> SCH : Updation in LC List Failed");
1031                /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
1032                if(!dciSlotAlloc->dlMsgPdschCfg)
1033                {
1034                   SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1035                   (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
1036                }
1037                return accumalatedSize;
1038             }
1039          }
1040       }//End of for loop
1041
1042       if ((fcfsHqProcCb->lcCb.defLcList.count == 0) && (fcfsHqProcCb->lcCb.dedLcList.count == 0))
1043       {
1044          DU_LOG("\nDEBUG  -->  SCH : No pending BO for any LC id\n");
1045          UNSET_ONE_BIT((*hqP)->hqEnt->ue->ueId, (*hqP)->hqEnt->cell->boIndBitMap);
1046
1047          /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
1048          if(!dciSlotAlloc->dlMsgPdschCfg)
1049          {
1050             SCH_FREE(dciSlotAlloc, sizeof(DlMsgSchInfo));
1051             (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
1052          }
1053          /*TRUE because this UE has nothing to be scheduled*/
1054          return accumalatedSize;
1055       }
1056    }
1057
1058    /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
1059    maxFreePRB = searchLargestFreeBlock((*hqP)->hqEnt->cell, pdschTime, startPrb, DIR_DL);
1060
1061    /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
1062     * the list based on RRM policy*/
1063
1064    /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or 
1065     * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
1066    if(isRetx == FALSE)
1067    {
1068       if(maxFreePRB != 0)
1069       {
1070          mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
1071
1072          if((fcfsHqProcCb->lcCb.dedLcList.count == NULLP) || ((maxFreePRB < rsvdDedicatedPRB)))
1073          { 
1074             fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB;
1075             DU_LOG("\nDEBUG  -->  SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
1076                   fcfsHqProcCb->lcCb.sharedNumPrb);
1077
1078             /*PRB Alloc for Default LCs*/
1079             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
1080                   &(fcfsHqProcCb->lcCb.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
1081          }
1082          else
1083          {
1084             fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
1085             /*PRB Alloc for Dedicated LCs*/
1086             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
1087                   &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
1088
1089             /*PRB Alloc for Default LCs*/
1090             prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
1091                   &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
1092          }
1093       }
1094    }
1095
1096    /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
1097     * using allocated BO per LC and Update dlMsgAlloc BO report for MAC */
1098    if (isRetx == FALSE)
1099    {
1100       if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
1101          updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
1102
1103       updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
1104    }
1105    else
1106    {
1107       accumalatedSize = (*hqP)->tbInfo[0].tbSzReq;
1108    }
1109
1110    /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
1111    if (!accumalatedSize)
1112    {
1113       if(maxFreePRB == 0)
1114       {
1115          DU_LOG("\nERROR  --> SCH : NO FREE PRB!!");
1116       }
1117       else
1118       {
1119          /*Schedule the LC for next slot*/
1120          DU_LOG("\nDEBUG  -->  SCH : No LC has been scheduled");
1121       }
1122       /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
1123        * Allocation can be done in next slot*/
1124       accumalatedSize = 0;
1125    }
1126
1127    return accumalatedSize;
1128 }
1129
1130 /*******************************************************************
1131  *
1132  * @brief Scheduling of Slots in UL And DL 
1133  *
1134  * @details
1135  *
1136  *    Function : schFcfsScheduleSlot
1137  *
1138  *    Functionality: Scheduling of slots in UL and DL specific to 
1139  *       FCFS scheduling
1140  *
1141  * @params[in] Pointer to Cell
1142  *             Slot timing info
1143  *             Scheduler instance
1144  * @return void
1145  *
1146  * ****************************************************************/
1147 void schFcfsScheduleSlot(SchCellCb *cell, SlotTimingInfo *slotInd, Inst schInst)
1148 {
1149    SchFcfsCellCb  *fcfsCell;
1150    SchFcfsUeCb    *fcfsUeCb;
1151    SchDlHqProcCb  *hqP = NULLP;
1152    SchUlHqProcCb  *ulHqP = NULLP;
1153    CmLList        *pendingUeNode;
1154    CmLList        *node;
1155    uint8_t        ueId, ueCount = 0;
1156    bool           isRarPending = false, isRarScheduled = false;
1157    bool           isMsg4Pending = false, isMsg4Scheduled = false;
1158    bool           isDlMsgPending = false, isDlMsgScheduled = false;
1159    bool           isUlGrantPending = false, isUlGrantScheduled = false;
1160
1161    fcfsCell = (SchFcfsCellCb *)cell->schSpcCell;
1162
1163    /* Select first UE in the linked list to be scheduled next */
1164    pendingUeNode = fcfsCell->ueToBeScheduled.first;
1165    ueCount = fcfsCell->ueToBeScheduled.count;
1166
1167    while(pendingUeNode && ueCount > 0)
1168    {
1169       /*Since Multi-UE perTTI is not supported, re-init following parameters.*/
1170       isRarPending = false; isRarScheduled = false;
1171       isMsg4Pending = false; isMsg4Scheduled = false;
1172       isDlMsgPending = false; isDlMsgScheduled = false;
1173       isUlGrantPending = false; isUlGrantScheduled = false;
1174       if(pendingUeNode->node)
1175       {
1176          ueId = *(uint8_t *)(pendingUeNode->node);
1177          fcfsUeCb = (SchFcfsUeCb *)cell->ueCb[ueId-1].schSpcUeCb;
1178
1179          /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and 
1180           * PUSCH to receive MSG3 as per k0-k2 configuration*/
1181          if(cell->raReq[ueId-1] != NULLP)
1182          {
1183             isRarPending = true;
1184             isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
1185          }
1186
1187          /*MSG3 retransmisson*/
1188          if(cell->raCb[ueId-1].retxMsg3HqProc)
1189          {            
1190             schMsg3RetxSchedulingForUe(&(cell->raCb[ueId-1]));
1191          }
1192
1193          /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
1194           * PUCCH to receive UL msg as per k0-k1 configuration  */
1195          if (cell->ueCb[ueId-1].retxMsg4HqProc) //should work from dlmap later tbd
1196          {
1197             /* Retransmission of MSG4 */
1198             isMsg4Pending = true;
1199             if(schProcessMsg4Req(cell, *slotInd, ueId, TRUE, &cell->ueCb[ueId-1].retxMsg4HqProc) == ROK)
1200                isMsg4Scheduled = true;
1201          }
1202          else
1203          {
1204             /* First transmission of MSG4 */
1205             if(cell->raCb[ueId-1].msg4recvd)
1206             {
1207                isMsg4Pending = true;
1208                if(schProcessMsg4Req(cell, *slotInd, ueId, FALSE, &cell->ueCb[ueId-1].msg4HqProc) == ROK)
1209                   isMsg4Scheduled = true;
1210
1211                /* If MSG4 scheduling failed, free the newly assigned HARQ process */
1212                if(!isMsg4Scheduled)
1213                   schDlReleaseHqProcess(cell->ueCb[ueId-1].msg4HqProc);
1214             }
1215          }
1216
1217          if(isRarPending || isMsg4Pending)
1218          {
1219             /* If RAR or MSG is successfully scheduled then
1220              * remove UE from linked list since no pending msgs for this UE */
1221             if(isRarScheduled || isMsg4Scheduled)
1222             {
1223                schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
1224             }
1225             /* If RAR/MSG4 is pending but couldnt be scheduled then,
1226              * put this UE at the end of linked list to be scheduled later */
1227             else
1228             {
1229                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1230             }
1231          }
1232
1233 #ifdef NR_DRX 
1234          if((cell->ueCb[ueId-1].ueDrxInfoPres == true) && (cell->ueCb[ueId-1].drxUeCb.drxDlUeActiveStatus != true))
1235          {
1236             if(pendingUeNode->node)
1237             {
1238                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1239             }
1240          }
1241          else 
1242 #endif
1243          {
1244
1245             /* DL Data */
1246             node = NULLP;
1247             if(fcfsUeCb)
1248                node = fcfsUeCb->hqRetxCb.dlRetxHqList.first;
1249             if(node != NULLP)
1250             {
1251                /* DL Data ReTransmisson */
1252                isDlMsgPending = true;
1253                isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, TRUE, ((SchDlHqProcCb**) &(node->node)));
1254                if(isDlMsgScheduled)
1255                {
1256 #ifdef NR_DRX 
1257                   schDrxStopDlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchDlHqProcCb**) &(node->node)));
1258 #endif
1259                   schFcfsRemoveFrmDlHqRetxList(&cell->ueCb[ueId-1], node);
1260                }
1261             }
1262             else
1263             {
1264                /* DL Data new transmission */
1265                if((cell->boIndBitMap) & (1<<ueId))
1266                {
1267                   isDlMsgPending = true;               
1268                   isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, FALSE, &hqP);
1269
1270                   /* If DL scheduling failed, free the newly assigned HARQ process */
1271                   if(!isDlMsgScheduled)
1272                      schDlReleaseHqProcess(hqP);
1273                   else
1274                   {
1275 #ifdef NR_DRX
1276                      schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], gConfigInfo.gPhyDeltaDl + SCHED_DELTA);
1277 #endif
1278                   }
1279                }
1280             }
1281          }
1282 #ifdef NR_DRX 
1283          if((cell->ueCb[ueId-1].ueDrxInfoPres == true) && (cell->ueCb[ueId-1].drxUeCb.drxUlUeActiveStatus != true))
1284          {
1285             if(pendingUeNode->node)
1286             {
1287                cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1288             }
1289          }
1290          else 
1291 #endif
1292          {
1293             /* Scheduling of UL grant */
1294             node = NULLP;
1295             if(fcfsUeCb)
1296                node = fcfsUeCb->hqRetxCb.ulRetxHqList.first;
1297             if(node != NULLP)
1298             {
1299                /* UL Data ReTransmisson */
1300                isUlGrantPending = true;
1301                isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, TRUE, (SchUlHqProcCb**) &(node->node));
1302                if(isUlGrantScheduled)
1303                {
1304 #ifdef NR_DRX 
1305                   schDrxStopUlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchUlHqProcCb**) &(node->node)));
1306 #endif
1307                   schFcfsRemoveFrmUlHqRetxList(&cell->ueCb[ueId-1], node);
1308                }
1309             }
1310             else
1311             {
1312                /* UL Data new transmission */
1313                if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
1314                {
1315                   isUlGrantPending = true;
1316                   isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, FALSE, &ulHqP);
1317                   if(!isUlGrantScheduled)
1318                      schUlReleaseHqProcess(ulHqP, FALSE);
1319                   else
1320                   {
1321 #ifdef NR_DRX
1322                      schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], gConfigInfo.gPhyDeltaUl + SCHED_DELTA);
1323 #endif
1324                   }
1325                }
1326             }
1327
1328             if(isUlGrantPending || isDlMsgPending)
1329             {
1330                if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
1331                {
1332                   cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
1333                }
1334                else
1335                {
1336                   schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
1337                }
1338             }
1339          }
1340       }
1341       if(!isUlGrantPending && !isDlMsgPending && !isRarPending && !isMsg4Pending)
1342       {
1343          DU_LOG("\nERROR  -->  SCH: In SchFcfsScheduleSlot, UE:%d is wrongly queued\
1344                in Pending UE List without any actions, Removing the UE from the list",ueId);
1345          schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
1346       }
1347       if(cell->schDlSlotInfo[slotInd->slot]->prbAlloc.numPrbAlloc >= MAX_NUM_RB)
1348       {
1349          DU_LOG("\nINFO   -->  SCH: No PRB available to proceed with next UE");
1350          return;     
1351       }
1352       pendingUeNode = fcfsCell->ueToBeScheduled.first;
1353       ueCount--;
1354    }
1355 }
1356
1357 /*******************************************************************
1358  *
1359  * @brief Initializes all function pointers to FCFS function handler
1360  *
1361  * @details
1362  *
1363  *    Function : schFcfsAllApisInit
1364  *
1365  *    Functionality: Initializes all function pointers to FCFS 
1366  *       function handler
1367  *
1368  * @params[in] Function pointer array
1369  * @return void
1370  *
1371  * ****************************************************************/
1372 void schFcfsAllApisInit(SchAllApis *allFcfsApi)
1373 {
1374     /* Interface API function pointers */
1375     allFcfsApi->SchCellCfgReq = schFcfsCellCfgReq;
1376     allFcfsApi->SchCellDeleteReq = schFcfsCellDelReq;
1377     allFcfsApi->SchAddUeConfigReq = SchFcfsAddUeConfigReq;
1378     allFcfsApi->SchModUeConfigReq = SchFcfsModUeConfigReq;
1379     allFcfsApi->SchUeDeleteReq = SchFcfsUeDeleteReq; 
1380     allFcfsApi->SchDlHarqInd = SchFcfsDlHarqInd; 
1381     allFcfsApi->SchCrcInd = schFcfsProcessCrcInd;
1382     allFcfsApi->SchRachInd = schFcfsProcessRachInd;
1383     allFcfsApi->SchPagingInd = schFcfsPagingInd;
1384     allFcfsApi->SchRachRsrcReq = schFcfsRachRsrcReq; 
1385     allFcfsApi->SchRachRsrcRel = schFcfsRachRsrcRel;
1386     allFcfsApi->SchDlRlcBoInfo = schFcfsDlRlcBoInfo;
1387     allFcfsApi->SchSrUciInd = schFcfsSrUciInd;
1388     allFcfsApi->SchBsr = schFcfsBsr;
1389
1390     /* Internal API function pointers */
1391     allFcfsApi->SchAddToDlHqRetxList = schFcfsAddToDlHqRetxList;
1392     allFcfsApi->SchAddToUlHqRetxList = schFcfsAddToUlHqRetxList;
1393     allFcfsApi->SchRemoveFrmDlHqRetxList = schFcfsRemoveFrmDlHqRetxList;
1394     allFcfsApi->SchRemoveFrmUlHqRetxList = schFcfsRemoveFrmUlHqRetxList;
1395     allFcfsApi->SchAddUeToSchedule = schFcfsAddUeToSchedule;
1396     allFcfsApi->SchRemoveUeFrmScheduleLst = schFcfsRemoveUeFrmScheduleLst;
1397     allFcfsApi->SchInitDlHqProcCb = schFcfsInitDlHqProcCb;
1398     allFcfsApi->SchInitUlHqProcCb = schFcfsInitUlHqProcCb;
1399     allFcfsApi->SchFreeDlHqProcCb = schFcfsFreeDlHqProcCb;
1400     allFcfsApi->SchFreeUlHqProcCb = schFcfsFreeUlHqProcCb;
1401     allFcfsApi->SchDeleteDlHqProcCb = schFcfsDeleteDlHqProcCb;
1402     allFcfsApi->SchDeleteUlHqProcCb = schFcfsDeleteUlHqProcCb;
1403     allFcfsApi->SchScheduleSlot = schFcfsScheduleSlot;
1404     allFcfsApi->SchScheduleDlLc = schFcfsScheduleDlLc;
1405     allFcfsApi->SchScheduleUlLc = schFcfsScheduleUlLc;
1406 }
1407 /**********************************************************************
1408     End of file
1409 **********************************************************************/
1410