1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 *******************************************************************************/
20 * @file This file has Shared Memory interface functions between FAPI and MAC
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"
32 static p_fapi_api_queue_elem_t p_fapi2mac_buffers;
34 //------------------------------------------------------------------------------
35 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
37 * @param data Pointer to validate
39 * @return TRUE If pointer is within valid shared WLS memory region
40 * FALSE If pointer is out of valid shared WLS memory region
43 * This function validates pointer's in WLS shared memory region
46 //------------------------------------------------------------------------------
47 uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
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)) {
60 //------------------------------------------------------------------------------
61 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
65 * @return A pointer to WLS_HANDLE stucture
68 * This function returns the WLS instance
71 //------------------------------------------------------------------------------
72 static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
75 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
77 return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
80 //------------------------------------------------------------------------------
81 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
85 * @return Pointer to the memory block
88 * This function allocates a block of memory from the pool
91 //------------------------------------------------------------------------------
92 void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
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();
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"));
105 if (p_fapi2mac_buffers) {
106 p_va_block = (void *)p_fapi2mac_buffers;
107 p_fapi2mac_buffers = p_fapi2mac_buffers->p_next;
109 pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
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"));
117 //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
120 p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
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"));
130 //------------------------------------------------------------------------------
131 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
135 * @return Pointer to the memory block
138 * This function allocates a block of memory from the pool
141 //------------------------------------------------------------------------------
142 void nr5g_fapi_fapi2mac_wls_free_buffer(
145 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
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"));
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;
156 p_fapi2mac_buffers = (p_fapi_api_queue_elem_t) buffers;
157 p_fapi2mac_buffers->p_next = NULL;
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"));
167 //------------------------------------------------------------------------------
168 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
172 * @return 0 if SUCCESS
175 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
179 //------------------------------------------------------------------------------
180 uint8_t nr5g_fapi_fapi2mac_wls_ready(
184 ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
188 //------------------------------------------------------------------------------
189 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
193 * @return Number of blocks of APIs received
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.
200 //------------------------------------------------------------------------------
201 uint32_t nr5g_fapi_fapi2mac_wls_wait(
205 // NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
206 ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
210 //------------------------------------------------------------------------------
211 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
213 * @param[out] data Location where First API from L1 is stored
215 * @return Size of Message sent from L1
218 * This function checks if this is the last message in this tti.
221 //------------------------------------------------------------------------------
222 static inline uint8_t is_msg_present(
225 return (!((flags & WLS_TF_FIN) || (flags == 0)));
228 //------------------------------------------------------------------------------
229 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
231 * @param[out] data Location where First API from L1 is stored
233 * @return Size of Message sent from L1
236 * This function queries the APIs sent from L1 to L2 and gets the first pointer
240 //------------------------------------------------------------------------------
241 uint64_t *nr5g_fapi_fapi2mac_wls_get(
246 uint64_t *data = NULL;
249 uint16_t mt = 0, f = 0;
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));
260 //------------------------------------------------------------------------------
261 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
263 * @param[in] ptr Pointer to the block to send
264 * @param[in] size Size of the block to send
266 * @return 0 if SUCCESS
269 * This function sends a single block of API from PHY to MAC
272 //------------------------------------------------------------------------------
273 inline uint8_t nr5g_fapi_fapi2mac_wls_put(
274 p_fapi_api_queue_elem_t p_msg,
279 uint8_t ret = SUCCESS;
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));
286 ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
291 //------------------------------------------------------------------------------
292 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
294 * @param[in] p_list Pointer to the linked list head
296 * @return 0 if SUCCESS
299 * This function sends a linked list of APIs from PHY to MAC.
302 //------------------------------------------------------------------------------
303 uint8_t nr5g_fapi_fapi2mac_wls_send(
304 p_fapi_api_queue_elem_t p_list_elem,
307 uint8_t ret = SUCCESS;
308 p_fapi_api_queue_elem_t p_curr_msg = NULL;
309 fapi_msg_t *p_msg_header = NULL;
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();
315 p_curr_msg = p_list_elem;
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"));
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)) {
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"));
336 p_curr_msg = p_curr_msg->p_next;
337 flags = WLS_SG_NEXT | flags_urllc;
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)) {
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"));
355 p_curr_msg = p_curr_msg->p_next;
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)) {
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"));
371 flags = WLS_SG_NEXT | flags_urllc;
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"));
380 tick_total_wls_send_per_tti_ul += __rdtsc() - start_tick;
385 //------------------------------------------------------------------------------
386 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
388 * @param[out] data Location where First API from L1 is stored
390 * @return Size of Message sent from L1
393 * This function queries the APIs sent from L1 to L2 and gets the first pointer
397 //------------------------------------------------------------------------------
398 p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
401 uint16_t msg_type = 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;
412 num_elms = nr5g_fapi_fapi2mac_wls_wait();
416 start_tick = __rdtsc();
418 p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
420 p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
422 if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
423 printf("Error: Invalid Ptr\n");
426 p_qelm->p_next = NULL;
428 if (flags & WLS_TF_URLLC)
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;
435 p_urllc_tail_qelm->p_next = p_qelm;
437 p_urllc_qelm_list = p_qelm;
441 p_tail_qelm = p_qelm_list;
442 while (NULL != p_tail_qelm->p_next) {
443 p_tail_qelm = p_tail_qelm->p_next;
445 p_tail_qelm->p_next = p_qelm;
447 p_qelm_list = p_qelm;
452 } while (num_elms && is_msg_present(flags));
454 if (p_urllc_qelm_list) {
455 nr5g_fapi_urllc_thread_callback(NR5G_FAPI_URLLC_MSG_DIR_MAC2PHY, (void *) p_urllc_qelm_list);
458 tick_total_wls_get_per_tti_dl += __rdtsc() - start_tick;