Merge "Restructure O1 module to run as a thread in O-DU High binary [Issue-Id: ODUHIG...
[o-du/l2.git] / src / 5gnrmac / lwr_mac_phy.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 /* This file contains APIs to send/receive messages from PHY */
20
21 #include "common_def.h"
22 #include "lrg.h"
23 #include "lrg.x"
24 #include "du_app_mac_inf.h"
25 #include "mac_sch_interface.h"
26 #include "lwr_mac_upr_inf.h"
27 #include "mac.h"
28 #include "lwr_mac_fsm.h"
29 #include "lwr_mac_phy.h"
30 #include "mac_utils.h"
31 #include "lwr_mac_utils.h"
32 #include "lwr_mac.h"
33 #ifdef INTEL_FAPI
34 #include "fapi.h"
35 #include "fapi_vendor_extension.h"
36 #endif
37 #ifdef INTEL_WLS_MEM
38 #include "wls_lib.h"
39 #endif
40
41 uint8_t rgClHndlCfgReq ARGS((void *msg));
42 void l1ProcessFapiRequest ARGS((uint8_t msgType, uint32_t msgLen, void *msg));
43
44 #ifdef INTEL_WLS_MEM
45
46 /*******************************************************************
47  *
48  * @brief Sends request to start wls receiver thread
49  *
50  * @details
51  *
52  *    Function : LwrMacStartWlsRcvr
53  *
54  *    Functionality:
55  *      Sends request to start wls receiver thread
56  *
57  * @params[in] 
58  * @return void
59  *
60  * ****************************************************************/
61 void LwrMacStartWlsRcvr()
62 {
63    Pst pst;
64    Buffer *mBuf;
65
66    DU_LOG("\nINFO  -->  LWR MAC : Requesting to start WLS receiver thread");
67
68    /* Filling post */
69    memset(&pst, 0, sizeof(Pst));
70    FILL_PST_LWR_MAC_TO_LWR_MAC(pst, EVT_START_WLS_RCVR);
71
72    if (ODU_GET_MSG_BUF(pst.region, pst.pool, &mBuf) != ROK)
73    {
74       DU_LOG("\nERROR  -->  LWR MAC : Memory allocation failed for LwrMacStartWlsRcvr");
75       return;
76    }
77
78    ODU_POST_TASK(&pst, mBuf);
79 }
80
81 /*******************************************************************
82  *
83  * @brief Enqueues memory blocks for use by L1
84  *
85  * @details
86  *
87  *    Function : LwrMacEnqueueWlsBlock
88  *
89  *    Functionality:
90  *      Enqueues memory blocks for use by L1
91  *
92  * @params[in] 
93  * @return void
94  *
95  * ****************************************************************/
96 void LwrMacEnqueueWlsBlock()
97 {
98    void *memPtr;
99    void *wlsHdlr = NULLP;
100
101    WLS_MEM_ALLOC(memPtr, LWR_MAC_WLS_BUF_SIZE);
102
103    if(memPtr) 
104    {
105       mtGetWlsHdl(&wlsHdlr);
106       /* allocate blocks for UL transmittion */
107       while(WLS_EnqueueBlock(wlsHdlr, WLS_VA2PA(wlsHdlr, memPtr)))
108       {
109          WLS_MEM_ALLOC(memPtr, LWR_MAC_WLS_BUF_SIZE);
110          if(!memPtr)
111             break;
112       }
113
114       // free not enqueued block
115       if(memPtr)
116       {
117          WLS_MEM_FREE(memPtr, LWR_MAC_WLS_BUF_SIZE);
118       }
119    }
120 }/* LwrMacEnqueueWlsBlock */
121
122 /*******************************************************************
123  *
124  * @brief Add memory block (to be freed later) to list
125  *
126  * @details
127  *
128  *    Function : addWlsBlockToFree 
129  *
130  *    Functionality:
131  *       Add memory block (to be freed later) to list
132  *
133  * @params[in] 
134  * @return ROK     - success
135  *         RFAILED - failure
136  *
137  * ****************************************************************/
138 void addWlsBlockToFree(void *msg, uint32_t msgLen, uint8_t idx)
139 {
140    CmLList         *node = NULLP;
141    WlsBlockToFree  *block = NULLP;
142    MAC_ALLOC(block, sizeof(WlsBlockToFree));
143    if(block)
144    {
145       MAC_ALLOC(node, sizeof(CmLList));
146       if(node)
147       {
148          block->ptr = msg;
149          block->size = msgLen;
150
151          node->node = (PTR)block;
152          cmLListAdd2Tail(&wlsBlockToFreeList[idx], node);
153       }
154    }
155 }/* addWlsBlockToFree */
156
157
158 /*******************************************************************
159  *
160  * @brief Free DL Memory blocks stored in list
161  *
162  * @details
163  *
164  *    Function : freeWlsBlockList
165  *
166  *    Functionality: Free DL Memory blocks stored in list
167  *
168  * @params[in] Array index to be freed
169  * @return ROK     - success
170  *         RFAILED - failure
171  *
172  * ****************************************************************/
173 void freeWlsBlockList(uint8_t idx)
174 {
175    CmLList         *node;
176    WlsBlockToFree  *block;
177    if(wlsBlockToFreeList[idx].count)
178    {
179       CM_LLIST_FIRST_NODE(&wlsBlockToFreeList[idx], node);
180       while(node)
181       {
182          block = (WlsBlockToFree *)node->node;
183          cmLListDelFrm(&wlsBlockToFreeList[idx], node);
184          WLS_MEM_FREE(block->ptr, block->size);
185          MAC_FREE(block, sizeof(WlsBlockToFree));
186          MAC_FREE(node, sizeof(CmLList));
187          node = NULL;
188          CM_LLIST_FIRST_NODE(&wlsBlockToFreeList[idx], node);
189       }
190    }
191 }
192
193 /*******************************************************************
194  *
195  * @brief Receives msg from L1 
196  *
197  * @details
198  *
199  *    Function :LwrMacRecvPhyMsg 
200  *
201  *    Functionality:
202  *      Receives L1 Msg and enqueues memort for UL msg
203  *
204  * @params[in] 
205  * @return 
206  * ****************************************************************/
207 void LwrMacRecvPhyMsg()
208 {
209 #ifdef INTEL_FAPI
210    uint32_t numMsgToGet;   /* Number of Memory blocks to get */
211    void     *wlsHdlr;       /* WLS handler */
212    uint64_t l1Msg;         /* Message received */
213    void     *l1MsgPtr;
214    uint32_t msgSize;
215    uint16_t msgType;
216    uint16_t flag = 0;
217    p_fapi_api_queue_elem_t currElem  = NULLP;
218
219    mtGetWlsHdl(&wlsHdlr);
220    if(WLS_Ready(wlsHdlr) == 0) 
221    {
222       while(true)
223       {
224          numMsgToGet = WLS_Wait(wlsHdlr);
225          if(numMsgToGet == 0)
226          {
227             continue;
228          }
229
230          DU_LOG("\nDEBUG  -->  LWR_MAC : numMsgToGet %d", numMsgToGet);
231          while(numMsgToGet--)
232          {
233             currElem = NULLP;
234             l1Msg = (uint64_t)NULLP;
235             l1MsgPtr = NULLP;
236             l1Msg = WLS_Get(wlsHdlr, &msgSize, &msgType, &flag);
237             if(l1Msg)
238             {
239                l1MsgPtr = WLS_PA2VA(wlsHdlr, l1Msg); 
240                currElem = (p_fapi_api_queue_elem_t) l1MsgPtr;
241                if(currElem->msg_type != FAPI_VENDOR_MSG_HEADER_IND)
242                {
243                   procPhyMessages(currElem->msg_type, 0, (void *)(currElem + 1));
244                }
245                WLS_MEM_FREE(currElem, LWR_MAC_WLS_BUF_SIZE);
246             }
247          }
248          LwrMacEnqueueWlsBlock();
249       }
250    }
251 #endif
252 } /* LwrMacRecvPhyMsg */
253
254 #endif /* INTEL_WLS_MEM */
255
256 /*******************************************************************
257  *
258  * @brief Send FAPI messages to Intel PHY/Phy stub
259  *
260  * @details
261  *
262  *    Function : LwrMacSendToL1
263  *
264  *    Functionality: Send FAPI messages to Intel PHY/Phy stub
265  *
266  * @params[in] Message pointer
267  * @return ROK     - success
268  *         RFAILED - failure
269  *
270  * ****************************************************************/
271 uint8_t LwrMacSendToL1(void *msg)
272 {
273    uint8_t ret = ROK;
274 #ifdef INTEL_FAPI
275    uint16_t msgLen =0;
276    p_fapi_api_queue_elem_t currMsg = NULLP;
277
278 #ifdef INTEL_WLS_MEM
279    void * wlsHdlr = NULLP;
280
281    mtGetWlsHdl(&wlsHdlr);
282    if(msg)
283    {
284       currMsg = (p_fapi_api_queue_elem_t)msg;
285       msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
286       addWlsBlockToFree(currMsg, msgLen, (lwrMacCb.phySlotIndCntr-1));
287       if(currMsg->p_next == NULLP)
288       {
289          DU_LOG("\nERROR  -->  LWR MAC : There cannot be only one block to send");
290          return RFAILED;
291       }
292
293       /* Sending first block */
294       ret = WLS_Put(wlsHdlr, WLS_VA2PA(wlsHdlr, currMsg), msgLen, currMsg->msg_type, WLS_SG_FIRST);
295       if(ret != 0)
296       {
297          DU_LOG("\nERROR  -->  LWR MAC : Failure in sending message to PHY");
298          return RFAILED;
299       }
300       currMsg = currMsg->p_next;
301
302       while(currMsg)
303       {
304          /* Sending the next msg */
305          msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
306          addWlsBlockToFree(currMsg, msgLen, (lwrMacCb.phySlotIndCntr-1));
307          if(currMsg->p_next != NULLP)
308          {
309             ret = WLS_Put(wlsHdlr, WLS_VA2PA(wlsHdlr, currMsg), msgLen, currMsg->msg_type, WLS_SG_NEXT);
310             if(ret != 0)
311             {
312                DU_LOG("\nERROR  -->  LWR MAC : Failure in sending message to PHY");
313                return RFAILED;
314             }
315             currMsg = currMsg->p_next;
316          }
317          else
318          {
319             /* Sending last msg */
320             ret = WLS_Put(wlsHdlr, WLS_VA2PA(wlsHdlr, currMsg), msgLen, currMsg->msg_type, WLS_SG_LAST);
321             if(ret != 0)
322             {
323                DU_LOG("\nERROR  -->  LWR MAC : Failure in sending message to PHY");
324                return RFAILED;
325             }
326             currMsg = NULLP;
327          }
328       }
329    }
330 #else
331    p_fapi_api_queue_elem_t nextMsg = NULLP;
332
333    /* FAPI header and vendor specific msgs are freed here. Only 
334     * the main FAPI messages are sent to phy stub */
335    currMsg = (p_fapi_api_queue_elem_t)msg;
336    while(currMsg)
337    {
338       nextMsg = currMsg->p_next;
339       msgLen = currMsg->msg_len + sizeof(fapi_api_queue_elem_t);
340       if((currMsg->msg_type != FAPI_VENDOR_MSG_HEADER_IND) && \
341             (currMsg->msg_type != FAPI_VENDOR_MESSAGE))
342       {
343          l1ProcessFapiRequest(currMsg->msg_type, msgLen, currMsg);
344       }
345       else
346       {
347          LWR_MAC_FREE(currMsg, msgLen);   
348       }
349       currMsg = nextMsg;
350    }
351 #endif
352 #endif
353    return ret;
354 }
355
356 /**********************************************************************
357   End of file
358  **********************************************************************/