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