[Epic-ID: ODUHIGH-402][Task-ID: ODUHIGH-418] Harq feature changes
[o-du/l2.git] / src / 5gnrmac / mac_slot_ind.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17  *******************************************************************************/
18 /* header include files (.h) */
19 #include "common_def.h"
20 #include "lrg.h"
21 #include "lrg.x"
22 #include "du_app_mac_inf.h"
23 #include "mac_sch_interface.h"
24 #include "lwr_mac_upr_inf.h"
25 #include "rlc_mac_inf.h"
26 #include "mac.h"
27 #include "mac_upr_inf_api.h"
28 #include "lwr_mac.h"
29 #include "lwr_mac_fsm.h"
30 #include "mac_utils.h"
31 #include "mac_harq_dl.h"
32
33 /* function pointers for packing slot ind from mac to sch */
34 MacSchSlotIndFunc macSchSlotIndOpts[] =
35 {
36    packMacSchSlotInd,
37    MacSchSlotInd,
38    packMacSchSlotInd
39 };
40
41 /**
42  * @brief process DL allocation from scheduler
43  *
44  * @details
45  *
46  *     Function : MacProcDlAlloc 
47  *      
48  *      This function copied dl sch info in the mac slot info
49  *           
50  *  @param[in]  Pst            *pst
51  *  @param[in]  DL allocation from scheduler
52  *  @return
53  *      -# ROK 
54  *      -# RFAILED 
55  **/
56 uint8_t MacProcDlAlloc(Pst *pst, DlSchedInfo *dlSchedInfo)
57 {
58    uint8_t   schInfoIdx = 0, cwIdx = 0;
59    uint8_t   ueId = 0, ueIdx = 0;
60    uint16_t  cellIdx = 0;
61    uint8_t   *retxTb = NULLP, *txPdu = NULLP;
62    uint16_t  txPduLen = 0;
63    MacDlSlot      *currDlSlot = NULLP;
64    DlMsgSchInfo   schedInfo;
65    DlHarqProcCb   *hqProcCb = NULLP;
66
67 #ifdef CALL_FLOW_DEBUG_LOG
68    DU_LOG("\nCall Flow: ENTSCH -> ENTMAC : EVENT_DL_SCH_INFO\n");
69 #endif
70    if(dlSchedInfo != NULLP)
71    {
72       GET_CELL_IDX(dlSchedInfo->cellId, cellIdx);
73       if(dlSchedInfo->isBroadcastPres)
74       {
75          currDlSlot = &macCb.macCell[cellIdx]->\
76                       dlSlot[dlSchedInfo->schSlotValue.broadcastTime.slot];
77          currDlSlot->dlInfo.isBroadcastPres = true;
78          memcpy(&currDlSlot->dlInfo.brdcstAlloc, &dlSchedInfo->brdcstAlloc, sizeof(DlBrdcstAlloc));
79          currDlSlot->dlInfo.brdcstAlloc.sib1Alloc.sib1PdcchCfg.dci.pdschCfg = \
80                                             &currDlSlot->dlInfo.brdcstAlloc.sib1Alloc.sib1PdschCfg;
81       }
82
83       for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
84       {
85          if(dlSchedInfo->rarAlloc[ueIdx] != NULLP)
86          {
87             currDlSlot = &macCb.macCell[cellIdx]->dlSlot[dlSchedInfo->schSlotValue.rarTime.slot];
88             currDlSlot->dlInfo.rarAlloc[ueIdx] = dlSchedInfo->rarAlloc[ueIdx];
89
90             /* MUXing of RAR */
91             fillRarPdu(&currDlSlot->dlInfo.rarAlloc[ueIdx]->rarInfo);
92          }
93
94          if(dlSchedInfo->dlMsgAlloc[ueIdx] != NULLP)
95          {
96             currDlSlot = &macCb.macCell[cellIdx]->\
97                          dlSlot[dlSchedInfo->schSlotValue.dlMsgTime.slot];
98             currDlSlot->dlInfo.dlMsgAlloc[ueIdx] = dlSchedInfo->dlMsgAlloc[ueIdx]; /* copy msg4 alloc pointer in MAC slot info */
99             currDlSlot->dlInfo.cellId = dlSchedInfo->cellId;
100
101             /* Check if the downlink pdu is msg4 */
102             for(schInfoIdx=0; schInfoIdx < dlSchedInfo->dlMsgAlloc[ueIdx]->numSchedInfo; schInfoIdx++)
103             {
104                if(dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.isMsg4Pdu)
105                {
106                   GET_UE_ID(dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.crnti, ueId);
107                   ueIdx = ueId -1;
108                   schedInfo = dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx];
109                   hqProcCb = &macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4HqInfo;
110
111                   if(!dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].isRetx)
112                   {
113                      /* First transmission of MSG4 */
114                      hqProcCb->procId = schedInfo.dlMsgInfo.harqProcNum;
115                      for(cwIdx = 0; cwIdx < schedInfo.dlMsgPdschCfg.numCodewords; cwIdx++)
116                      {
117                         memcpy(&hqProcCb->tbInfo[hqProcCb->numTb].txTime, &dlSchedInfo->schSlotValue.dlMsgTime, \
118                               sizeof(SlotTimingInfo));
119                         hqProcCb->tbInfo[hqProcCb->numTb].tbSize = schedInfo.dlMsgPdschCfg.codeword[cwIdx].tbSize;
120                         hqProcCb->numTb++;
121                      }
122                   }
123                   else
124                   {
125                      /* MSG4 retransmission */
126                      if(hqProcCb->procId == schedInfo.dlMsgInfo.harqProcNum)
127                      {
128                         memcpy(&hqProcCb->tbInfo[0].txTime, &dlSchedInfo->schSlotValue.dlMsgTime, \
129                                                      sizeof(SlotTimingInfo));
130                      }
131                   }
132                }
133                else
134                {
135                   memcpy(&currDlSlot->dlInfo.schSlotValue, &dlSchedInfo->schSlotValue, sizeof(SchSlotValue));
136                   
137                   if(!dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].isRetx)
138                   {
139                      /* If new data transmission is scheduled, send schedule results to RLC */
140                      if((dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].pduPres == PDSCH_PDU) ||
141                            (dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].pduPres == BOTH))
142                      {
143                         sendSchedRptToRlc(currDlSlot->dlInfo, dlSchedInfo->schSlotValue.dlMsgTime, ueIdx, schInfoIdx);
144
145                         /* Add HARQ Proc to DL HARQ Proc Entity in UE */
146                         addDlHqProcInUe(currDlSlot->dlInfo.schSlotValue.dlMsgTime, &macCb.macCell[cellIdx]->ueCb[ueIdx], \
147                            dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx]);
148                      }
149                   }
150                   else
151                   {
152                      /* For retransmission, fetch PDU to be retransmitted from DL HARQ entity and schedule on corresponding slot */
153                      
154                      /* As of now this loop will run only once for one TB. 
155                       * TODO : update handling of fetched TB appropriately when support for two TB is added 
156                       */
157                      for(cwIdx = 0; \
158                            cwIdx < dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgPdschCfg.numCodewords;\
159                            cwIdx++)
160                      {
161                         /* Fetch TB to be retransmitted */
162                         txPduLen = dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgPdschCfg.codeword[cwIdx].tbSize;
163                         retxTb = fetchTbfromDlHarqProc(currDlSlot->dlInfo.schSlotValue.dlMsgTime, \
164                               &macCb.macCell[cellIdx]->ueCb[ueIdx], \
165                               dlSchedInfo->dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.harqProcNum, txPduLen);
166
167                         /* Store PDU in corresponding DL slot */
168                         MAC_ALLOC(txPdu, txPduLen);
169                         if(!txPdu)
170                         {
171                            DU_LOG("\nERROR  -->  MAC : Memory allocation failed in MacProcRlcDlData");
172                            return RFAILED;
173                         }   
174                         memcpy(txPdu, retxTb,  txPduLen);
175
176                         currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.dlMsgPduLen = txPduLen;
177                         currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.dlMsgPdu = txPdu;
178                      }
179                   }
180                }
181             }
182          }
183       }
184
185       if(dlSchedInfo->ulGrant != NULLP)
186       {
187          currDlSlot = &macCb.macCell[cellIdx]->dlSlot[dlSchedInfo->schSlotValue.ulDciTime.slot];
188          currDlSlot->dlInfo.ulGrant = dlSchedInfo->ulGrant;
189       }
190    }
191    return ROK;
192 }
193
194 /**
195  * @brief process DL Paging allocation from scheduler
196  *
197  * @details
198  *
199  *     Function : MacProcDlPageAlloc 
200  *      
201  *      This function copied dl Pag info in the mac slot info
202  *           
203  *  @param[in]  Pst            *pst
204  *  @param[in]  DL Paging allocation from scheduler
205  *  @return
206  *      -# ROK 
207  *      -# RFAILED 
208  **/
209 uint8_t MacProcDlPageAlloc(Pst *pst, DlPageAlloc *dlPageAlloc)
210 {
211    uint16_t  cellIdx = 0;
212    MacDlSlot *currDlSlot = NULLP;
213
214 #ifdef CALL_FLOW_DEBUG_LOG
215    DU_LOG("\nCall Flow: ENTSCH -> ENTMAC : EVENT_DL_PAGING_ALLOC\n");
216 #endif
217    if(dlPageAlloc != NULLP)
218    {
219       GET_CELL_IDX(dlPageAlloc->cellId, cellIdx);
220
221       currDlSlot = &macCb.macCell[cellIdx]->dlSlot[dlPageAlloc->dlPageTime.slot];
222       MAC_ALLOC(currDlSlot->pageAllocInfo, sizeof(DlPageAlloc));
223       if(currDlSlot->pageAllocInfo == NULLP)
224       {
225          DU_LOG("\nERROR  --> MAC : MacProcDlPageAlloc : Memory Allocation is failed!");
226          return RFAILED;
227       }
228       memcpy(currDlSlot->pageAllocInfo, dlPageAlloc, sizeof(DlPageAlloc));
229       currDlSlot->pageAllocInfo->pagePdcchCfg.dci.pdschCfg = \
230                                                              &currDlSlot->pageAllocInfo->pagePdschCfg;
231    }
232    else
233    {
234       DU_LOG("\nERROR  --> MAC : DL Paging Allocation is failed!");
235       return RFAILED;
236    }
237    return ROK;
238 }
239
240 /**
241  * @brief Forming and filling the MUX Pdu
242  * @details
243  *
244  *     Function : fillMsg4Pdu
245  * 
246  *      Forming and filling of Msg4Pdu
247  *           
248  *  @param[in]  DlMsgAlloc  *msg4Alloc
249  *  @return  void
250  **/
251 void fillMsg4Pdu(uint16_t cellId, DlMsgSchInfo *msg4SchInfo)
252 {
253    uint8_t   ueId = 0, ueIdx = 0;
254    uint16_t  cellIdx;
255    uint16_t  msg4TxPduLen;
256    MacDlData msg4DlData;
257    MacCeInfo  macCeData;
258    DlHarqProcCb *hqProcCb;
259
260    GET_CELL_IDX(cellId, cellIdx);
261
262    memset(&msg4DlData, 0, sizeof(MacDlData));
263    memset(&macCeData, 0, sizeof(MacCeInfo));
264
265    GET_UE_ID(msg4SchInfo->dlMsgInfo.crnti, ueId);
266    ueIdx = ueId -1;
267
268    if(macCb.macCell[cellIdx] == NULLP)
269    {
270       DU_LOG("\nERROR -->  MAC: Cell Id[%d] not found", cellId);
271       return;
272    }
273
274    hqProcCb = &macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4HqInfo;
275    msg4TxPduLen = hqProcCb->tbInfo[0].tbSize - TX_PAYLOAD_HDR_LEN;
276
277    if(macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4Pdu != NULLP)
278    {
279       MAC_ALLOC(msg4DlData.pduInfo[msg4DlData.numPdu].dlPdu, macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4PduLen);
280       if(msg4DlData.pduInfo[msg4DlData.numPdu].dlPdu != NULLP)
281       {
282          fillMsg4DlData(&msg4DlData, macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4PduLen, \
283             macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4Pdu);
284          fillMacCe(&macCeData, macCb.macCell[cellIdx]->macRaCb[ueIdx].msg3Pdu);
285
286          /* Forming Mux Pdu */
287          hqProcCb->tbInfo[0].tb = NULLP;
288          MAC_ALLOC(hqProcCb->tbInfo[0].tb, msg4TxPduLen);
289          if(hqProcCb->tbInfo[0].tb != NULLP)
290          {
291             memset(hqProcCb->tbInfo[0].tb, 0, msg4TxPduLen);
292             macMuxPdu(&msg4DlData, &macCeData, hqProcCb->tbInfo[0].tb, msg4TxPduLen);
293          }
294          else
295          {
296             DU_LOG("\nERROR  -->  MAC: Failed allocating memory for msg4TxPdu");
297          }
298          /* Free memory allocated */
299          MAC_FREE(msg4DlData.pduInfo[msg4DlData.numPdu-1].dlPdu, macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4PduLen);
300          MAC_FREE(macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4Pdu, macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4PduLen);
301          macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4Pdu = NULLP;
302          macCb.macCell[cellIdx]->macRaCb[ueIdx].msg4PduLen = 0;
303          msg4DlData.numPdu--;
304
305       }
306    }
307
308    /* storing msg4 Pdu in macDlSlot */
309    if(hqProcCb->tbInfo[0].tb)
310    {
311       msg4SchInfo->dlMsgInfo.dlMsgPduLen = msg4TxPduLen;
312       MAC_ALLOC(msg4SchInfo->dlMsgInfo.dlMsgPdu, msg4SchInfo->dlMsgInfo.dlMsgPduLen);
313       if(msg4SchInfo->dlMsgInfo.dlMsgPdu != NULLP)
314       {
315          memcpy(msg4SchInfo->dlMsgInfo.dlMsgPdu, hqProcCb->tbInfo[0].tb, \
316                msg4SchInfo->dlMsgInfo.dlMsgPduLen);
317       }
318    }
319    else
320    {
321       DU_LOG("\nERROR  -->  MAC: Failed at fillMsg4Pdu()");
322    }
323 }
324
325 /**
326  * @brief Builds and Send the Muxed Pdu to Lower MAC
327  *
328  * @details
329  *
330  *     Function : buildAndSendMuxPdu
331  * 
332  *      Build and Sends the Muxed Pdu to Lower MAC.
333  *           
334  *  @param[in]  SlotTimingInfo    *slotInd
335  *  @return  void
336  **/
337
338 void buildAndSendMuxPdu(SlotTimingInfo currTimingInfo)
339 {
340    uint8_t   ueIdx;
341    uint8_t   schInfoIdx;
342    uint16_t  cellIdx;
343    MacDlSlot *currDlSlot = NULLP;
344    SlotTimingInfo muxTimingInfo;
345    memset(&muxTimingInfo, 0, sizeof(SlotTimingInfo));
346
347    GET_CELL_IDX(currTimingInfo.cellId, cellIdx);
348
349    ADD_DELTA_TO_TIME(currTimingInfo, muxTimingInfo, PHY_DELTA_DL);
350    currDlSlot = &macCb.macCell[cellIdx]->dlSlot[muxTimingInfo.slot];
351
352    for(ueIdx=0; ueIdx<MAX_NUM_UE; ueIdx++)
353    {
354       if(currDlSlot->dlInfo.dlMsgAlloc[ueIdx])
355       {
356          for(schInfoIdx=0; schInfoIdx<currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->numSchedInfo; schInfoIdx++)
357          {
358             if((currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].dlMsgInfo.isMsg4Pdu) &&
359                   ((currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].pduPres == PDSCH_PDU) ||
360                    (currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx].pduPres == BOTH)))
361             {
362                fillMsg4Pdu(currTimingInfo.cellId, &currDlSlot->dlInfo.dlMsgAlloc[ueIdx]->dlMsgSchedInfo[schInfoIdx]);
363             }
364          }
365       }
366    }
367 }
368
369 /**
370  * @brief Transmission time interval indication from PHY.
371  *
372  * @details
373  *
374  *     Function : sendSlotIndMacToSch
375  * 
376  *      This API is invoked by MAC to send slot ind to scheduler.
377  *           
378  *  @param[in]  SlotTimingInfo    *slotInd
379  *  @return  
380  *      -# ROK 
381  *      -# RFAILED 
382  **/
383 int sendSlotIndMacToSch(SlotTimingInfo *slotInd)
384 {
385    /* fill Pst structure to send to lwr_mac to MAC */
386    Pst pst;
387
388    FILL_PST_MAC_TO_SCH(pst, EVENT_SLOT_IND_TO_SCH);
389    return(*macSchSlotIndOpts[pst.selector])(&pst,slotInd);
390 }
391
392 /*******************************************************************
393  *
394  * @brief Send cell up indication to DU APP
395  *
396  * @details
397  *
398  *    Function : sendCellUpIndMacToDuApp
399  *
400  *    Functionality:
401  *       Send cell up indication to DU APP
402  *
403  * @params[in] Cell Up indication info 
404  * @return ROK     - success
405  *         RFAILED - failure
406  *
407  * ****************************************************************/
408 int sendCellUpIndMacToDuApp(uint16_t cellId)
409 {
410    Pst pst;
411    uint16_t ret;
412    OduCellId *oduCellId;
413
414    /*  Allocate sharable memory */
415    MAC_ALLOC_SHRABL_BUF(oduCellId, sizeof(OduCellId));
416    if(!oduCellId)
417    {
418       DU_LOG("\nERROR  -->  MAC : Memory allocation failed for cell up indication");
419       return RFAILED;
420    }
421    oduCellId->cellId = cellId;
422
423    /* Fill Pst */
424    FILL_PST_MAC_TO_DUAPP(pst, EVENT_MAC_CELL_UP_IND);
425
426    ret = MacDuAppCellUpInd(&pst, oduCellId);
427    if(ret != ROK)
428    {
429       DU_LOG("\nERROR  -->  MAC: Failed to send cell up indication to DU APP");
430       MAC_FREE_SHRABL_BUF(MAC_MEM_REGION, MAC_POOL, oduCellId, sizeof(OduCellId));
431    }
432
433    return ret;
434 } /* sendCellUpIndMacToDuApp */
435
436 /*******************************************************************
437  *
438  * @brief Send slot indication to DU APP
439  *
440  * @details
441  *
442  *    Function : sendSlotIndToDuApp
443  *
444  *    Functionality:
445  *       Send cell up indication to DU APP
446  *
447  * @params[in] Cell Up indication info 
448  * @return ROK     - success
449  *         RFAILED - failure
450  *
451  * ****************************************************************/
452 uint8_t sendSlotIndToDuApp(SlotTimingInfo *slotInd)
453 {
454    Pst pst;
455    uint16_t ret;
456    SlotTimingInfo *slotIndInfo;
457
458    /*  Allocate sharable memory */
459    MAC_ALLOC_SHRABL_BUF(slotIndInfo, sizeof(SlotTimingInfo));
460    if(!slotIndInfo)
461    {
462       DU_LOG("\nERROR  -->  MAC : Memory allocation failed for slot indication");
463       return RFAILED;
464    }
465    memcpy(slotIndInfo, slotInd,sizeof(SlotTimingInfo));
466
467    /* Fill Pst */
468    FILL_PST_MAC_TO_DUAPP(pst, EVENT_MAC_SLOT_IND);
469
470    ret = MacDuAppSlotInd(&pst, slotIndInfo);
471    if(ret != ROK)
472    {
473       DU_LOG("\nERROR  -->  MAC: Failed to send slot up indication to DU APP");
474       MAC_FREE_SHRABL_BUF(MAC_MEM_REGION, MAC_POOL, slotIndInfo, sizeof(SlotTimingInfo));
475    }
476
477    return ret;
478 }
479 /*******************************************************************
480  *
481  * @brief Process slot indication at MAC
482  *
483  * @details
484  *
485  *    Function : macProcSlotInd
486  *
487  *    Functionality: Process slot indication at MAC
488  *
489  * @params[in] Slot indication info
490  * @return ROK     - success
491  *         RFAILED - failure
492  *
493  * ****************************************************************/
494 uint8_t macProcSlotInd(SlotTimingInfo slotInd)
495 {
496    uint16_t  cellIdx = 0;
497
498    GET_CELL_IDX(slotInd.cellId, cellIdx);
499    
500    if(macCb.macCell[cellIdx] == NULLP)
501    {
502       DU_LOG("ERROR  --> MAC : macProcSlotInd(): CellId[%d] does not exist. Error occurred at SFN [%d] Slot [%d]",\
503       slotInd.cellId, slotInd.sfn, slotInd.slot);
504       return RFAILED;
505    }
506    /* Store current time info */
507    macCb.macCell[cellIdx]->currTime.cellId = slotInd.cellId;
508    macCb.macCell[cellIdx]->currTime.slot = slotInd.slot;
509    macCb.macCell[cellIdx]->currTime.sfn = slotInd.sfn;
510
511    /* Mux Pdu for Msg4 */
512    buildAndSendMuxPdu(slotInd);
513
514    /* Trigger for DL TTI REQ */
515    fillDlTtiReq(slotInd);
516
517    return ROK;
518 }  /* macProcSlotInd */
519
520 /**
521  * @brief Transmission time interval indication from PHY.
522  *
523  * @details
524  *
525  *     Function : fapiMacSlotInd 
526  *      
527  *      This API is invoked by PHY to indicate TTI indication to MAC for a cell.
528  *           
529  *  @param[in]  Pst            *pst
530  *  @param[in]  SuId           suId 
531  *  @param[in]  SlotTimingInfo    *slotInd
532  *  @return  
533  *      -# ROK 
534  *      -# RFAILED 
535  **/
536 uint8_t fapiMacSlotInd(Pst *pst, SlotTimingInfo *slotInd)
537 {
538    uint8_t               ret = ROK;
539    uint16_t              cellIdx;
540    volatile uint32_t     startTime=0;
541
542 #ifdef ODU_SLOT_IND_DEBUG_LOG
543    DU_LOG("\nDEBUG  -->  MAC : Slot Indication received. [%d : %d]", slotInd->sfn, slotInd->slot);
544 #endif
545    /*starting Task*/
546    ODU_START_TASK(&startTime, PID_MAC_TTI_IND);
547    gSlotCount++;
548
549    if(gSlotCount == 1)
550    {
551            GET_CELL_IDX(slotInd->cellId, cellIdx);
552            macCb.macCell[cellIdx]->state = CELL_STATE_UP;
553    }
554
555 /* When testing L2 with Intel-L1, any changes specific to 
556  * timer mode testing must be guarded under INTEL_TIMER_MODE*/
557 #ifndef INTEL_TIMER_MODE
558    /* send slot indication to scheduler */
559    ret = sendSlotIndMacToSch(slotInd);
560    if(ret != ROK)
561    {
562       DU_LOG("\nERROR  -->  MAC : Sending of slot ind msg from MAC to SCH failed");
563       MAC_FREE_SHRABL_BUF(pst->region, pst->pool, slotInd, sizeof(SlotTimingInfo));
564       return ret;
565    }
566
567    ret = macProcSlotInd(*slotInd);
568    if(ret != ROK)
569    {
570       DU_LOG("\nERROR  -->  MAC : macProcSlotInd failed");
571       MAC_FREE_SHRABL_BUF(pst->region, pst->pool, slotInd, sizeof(SlotTimingInfo));
572       return ret;
573    }
574 #endif
575
576    /*First Slot Ind is for CellUp. Any other Slot, will be notified to DUAPP as
577     * SLOT_IND*/
578    if(gSlotCount == 1)   
579    {
580       /* send cell up indication to du app */
581       ret = sendCellUpIndMacToDuApp(slotInd->cellId);
582
583    }
584    else
585    {
586       /* send slot indication to du app */
587       ret = sendSlotIndToDuApp(slotInd);
588    }
589    
590    if(ret != ROK)
591    {
592       DU_LOG("\nERROR  -->  MAC :Sending of slot ind msg from MAC to DU APP failed");
593       MAC_FREE_SHRABL_BUF(pst->region, pst->pool, slotInd, sizeof(SlotTimingInfo));
594       return ret;
595    }
596
597    /*stoping Task*/
598    ODU_STOP_TASK(startTime, PID_MAC_TTI_IND);
599    MAC_FREE_SHRABL_BUF(pst->region, pst->pool, slotInd, sizeof(SlotTimingInfo));
600
601 #ifdef INTEL_WLS_MEM
602    lwrMacCb.phySlotIndCntr++;
603    if(lwrMacCb.phySlotIndCntr > WLS_MEM_FREE_PRD)
604    {
605       lwrMacCb.phySlotIndCntr = 1;
606    }
607    freeWlsBlockList(lwrMacCb.phySlotIndCntr - 1);
608 #endif
609
610    return ret;
611 }  /* fapiMacSlotInd */
612
613 /**********************************************************************
614   End of file
615  **********************************************************************/
616