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