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