bded93ed31a7aea2c79261dcad02b86f638052f2
[o-du/phy.git] / fapi_5g / source / framework / wls / fapi2mac / nr5g_fapi_fapi2mac_wls.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
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  * @file This file has Shared Memory interface functions between FAPI and MAC 
21  *
22  **/
23
24 #include "nr5g_fapi_std.h"
25 #include "nr5g_fapi_common_types.h"
26 #include "nr5g_fapi_wls.h"
27 #include "gnb_l1_l2_api.h"
28 #include "nr5g_fapi_fapi2mac_wls.h"
29 #include "nr5g_fapi_log.h"
30
31 //------------------------------------------------------------------------------
32 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
33  *
34  *  @param data Pointer to validate
35  *
36  *  @return  TRUE If pointer is within valid shared WLS memory region
37  *           FALSE If pointer is out of valid shared WLS memory region
38  *
39  *  @description
40  *  This function validates pointer's in WLS shared memory region
41  *
42 **/
43 //------------------------------------------------------------------------------
44 uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
45     void *data)
46 {
47     p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
48     if ((unsigned long)data >= (unsigned long)p_wls_ctx->shmem &&
49         (unsigned long)data < ((unsigned long)p_wls_ctx->shmem +
50             p_wls_ctx->nPartitionMemSize)) {
51         return TRUE;
52     } else {
53         return FALSE;
54     }
55 }
56
57 //------------------------------------------------------------------------------
58 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
59  *
60  *  @param void
61  *
62  *  @return  A pointer to WLS_HANDLE stucture
63  *
64  *  @description
65  *  This function returns the WLS instance
66  *
67 **/
68 //------------------------------------------------------------------------------
69 static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
70     )
71 {
72     p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
73
74     return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
75 }
76
77 //------------------------------------------------------------------------------
78 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
79  *
80  *  @param   void
81  *
82  *  @return  Pointer to the memory block
83  *
84  *  @description
85  *  This function allocates a block of memory from the pool
86  *
87 **/
88 //------------------------------------------------------------------------------
89 void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
90     )
91 {
92     uint64_t pa_block = 0;
93     void *p_va_block = NULL;
94     p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
95     WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
96
97     if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->
98             fapi2mac_lock_alloc)) {
99         NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
100         return NULL;
101     }
102     pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
103     if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
104             fapi2mac_lock_alloc)) {
105         NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
106         return NULL;
107     }
108
109     if (!pa_block) {
110         //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
111         return NULL;
112     }
113     p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
114     return p_va_block;
115 }
116
117 //------------------------------------------------------------------------------
118 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
119  *
120  *  @param void
121  *
122  *  @return  0 if SUCCESS
123  *
124  *  @description
125  *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
126  *  needed by the L2
127  *
128 **/
129 //------------------------------------------------------------------------------
130 uint8_t nr5g_fapi_fapi2mac_wls_ready(
131     )
132 {
133     int ret = SUCCESS;
134     ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
135     return ret;
136 }
137
138 //------------------------------------------------------------------------------
139 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
140  *
141  *  @param   void
142  *
143  *  @return  Number of blocks of APIs received
144  *
145  *  @description
146  *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
147  *  during runtime when L2 sends a API to L1 and then waits for response back.
148  *
149 **/
150 //------------------------------------------------------------------------------
151 uint8_t nr5g_fapi_fapi2mac_wls_wait(
152     )
153 {
154     int ret = SUCCESS;
155 //    NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
156     ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
157     return ret;
158 }
159
160 //------------------------------------------------------------------------------
161 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
162  *
163  *  @param[out]   data Location where First API from L1 is stored
164  *
165  *  @return  Size of Message sent from L1
166  *
167  *  @description
168  *  This function checks if this is the last message in this tti.
169  *
170 **/
171 //------------------------------------------------------------------------------
172 static inline uint8_t is_msg_present(
173     uint16_t flags)
174 {
175     return (!((flags & WLS_TF_FIN) || (flags == 0)));
176 }
177
178 //------------------------------------------------------------------------------
179 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
180  *
181  *  @param[out]   data Location where First API from L1 is stored
182  *
183  *  @return  Size of Message sent from L1
184  *
185  *  @description
186  *  This function queries the APIs sent from L1 to L2 and gets the first pointer
187  *  to the linked list
188  *
189 **/
190 //------------------------------------------------------------------------------
191 uint64_t *nr5g_fapi_fapi2mac_wls_get(
192     uint32_t * msg_size,
193     uint16_t * msg_type,
194     uint16_t * flags)
195 {
196     uint64_t *data = NULL;
197     WLS_HANDLE h_wls;
198     uint32_t ms = 0;
199     uint16_t mt = 0, f = 0;
200
201     h_wls = nr5g_fapi_fapi2mac_wls_instance();
202     data = (uint64_t *) WLS_Get1(h_wls, &ms, &mt, &f);
203     *msg_size = ms, *msg_type = mt, *flags = f;
204     NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][GET] %p size: %d "
205             "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
206
207     return data;
208 }
209
210 //------------------------------------------------------------------------------
211 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
212  *
213  *  @param[in]   ptr Pointer to the block to send
214  *  @param[in]   size Size of the block to send
215  *
216  *  @return  0 if SUCCESS
217  *
218  *  @description
219  *  This function sends a single block of API from PHY to MAC
220  *
221 **/
222 //------------------------------------------------------------------------------
223 inline uint8_t nr5g_fapi_fapi2mac_wls_put(
224     p_fapi_api_queue_elem_t p_msg,
225     uint32_t msg_size,
226     uint16_t msg_type,
227     uint16_t flags)
228 {
229     uint8_t ret = SUCCESS;
230
231     WLS_HANDLE h_mac_wls = nr5g_fapi_fapi2mac_wls_instance();
232     uint64_t pa = nr5g_fapi_wls_va_to_pa(h_mac_wls, (void *)p_msg);
233     NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][PUT] %ld size: %d "
234             "type: %x flags: %x", pa, msg_size, msg_type, flags));
235
236     ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
237
238     return ret;
239 }
240
241 //------------------------------------------------------------------------------
242 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
243  *
244  *  @param[in]   p_list Pointer to the linked list head
245  *
246  *  @return  0 if SUCCESS
247  *
248  *  @description
249  *  This function sends a linked list of APIs from PHY to MAC.
250  *
251 **/
252 //------------------------------------------------------------------------------
253 uint8_t nr5g_fapi_fapi2mac_wls_send(
254     p_fapi_api_queue_elem_t p_list_elem)
255 {
256     uint8_t ret = SUCCESS;
257     p_fapi_api_queue_elem_t p_curr_msg = NULL;
258     fapi_msg_t *p_msg_header = NULL;
259     uint16_t flags = 0;
260     p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
261
262     p_curr_msg = p_list_elem;
263
264     if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2mac_lock_send)) {
265         NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
266         return FAILURE;
267     }
268
269     if (p_curr_msg && p_curr_msg->p_next) {
270         flags = WLS_SG_FIRST;
271         if (p_curr_msg->msg_type == FAPI_MSG_HEADER_IND) {
272             if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
273                     p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
274                     FAPI_MSG_HEADER_IND, flags)) {
275                 printf("Error\n");
276                 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
277                         fapi2mac_lock_send)) {
278                     NR5G_FAPI_LOG(ERROR_LOG,
279                         ("unable to unlock send pthread mutex"));
280                 }
281                 return FAILURE;
282             }
283             p_curr_msg = p_curr_msg->p_next;
284             flags = WLS_SG_NEXT;
285         }
286
287         while (p_curr_msg) {
288             // only batch mode
289             p_msg_header = (fapi_msg_t *) (p_curr_msg + 1);
290             if (p_curr_msg->p_next) {   // FIRST/NEXT
291                 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
292                         p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
293                         p_msg_header->msg_id, flags)) {
294                     printf("Error\n");
295                     if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
296                             fapi2mac_lock_send)) {
297                         NR5G_FAPI_LOG(ERROR_LOG,
298                             ("unable to unlock send pthread mutex"));
299                     }
300                     return FAILURE;
301                 }
302                 p_curr_msg = p_curr_msg->p_next;
303             } else {            // LAST
304                 flags = WLS_SG_LAST;
305                 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
306                         p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
307                         p_msg_header->msg_id, flags)) {
308                     printf("Error\n");
309                     if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
310                             fapi2mac_lock_send)) {
311                         NR5G_FAPI_LOG(ERROR_LOG,
312                             ("unable to unlock send pthread mutex"));
313                     }
314                     return FAILURE;
315                 }
316                 p_curr_msg = NULL;
317             }
318             flags = WLS_SG_NEXT;
319         }
320     }
321
322     if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
323             fapi2mac_lock_send)) {
324         NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
325         return FAILURE;
326     }
327     return ret;
328 }
329
330 //------------------------------------------------------------------------------
331 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
332  *
333  *  @param[out]   data Location where First API from L1 is stored
334  *
335  *  @return  Size of Message sent from L1
336  *
337  *  @description
338  *  This function queries the APIs sent from L1 to L2 and gets the first pointer
339  *  to the linked list
340  *
341 **/
342 //------------------------------------------------------------------------------
343 p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
344     )
345 {
346     uint16_t msg_type = 0;
347     uint16_t flags = 0;
348     uint32_t msg_size = 0;
349     uint32_t num_elms = 0;
350     uint64_t *p_msg = NULL;
351     p_fapi_api_queue_elem_t p_qelm_list = NULL;
352     p_fapi_api_queue_elem_t p_qelm = NULL;
353     p_fapi_api_queue_elem_t p_tail_qelm = NULL;
354     WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
355
356     num_elms = nr5g_fapi_fapi2mac_wls_wait();
357     if (!num_elms)
358         return p_qelm_list;
359
360     do {
361         p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
362         if (p_msg) {
363             p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
364                 (uint64_t) p_msg);
365             if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
366                 printf("Error: Invalid Ptr\n");
367                 continue;
368             }
369             p_qelm->p_next = NULL;
370             if (p_qelm_list) {
371                 p_tail_qelm = p_qelm_list;
372                 while (NULL != p_tail_qelm->p_next) {
373                     p_tail_qelm = p_tail_qelm->p_next;
374                 }
375                 p_tail_qelm->p_next = p_qelm;
376             } else {
377                 p_qelm_list = p_qelm;
378             }
379         }
380         num_elms--;
381     } while (num_elms && is_msg_present(flags));
382
383     return p_qelm_list;
384 }