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