1 /******************************************************************************
3 * Copyright (c) 2021 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 "nr5g_fapi_fapi2mac_wls.h"
28 #include "nr5g_fapi_log.h"
29 #include "nr5g_fapi_framework.h"
31 static p_fapi_api_queue_elem_t p_fapi2mac_buffers;
33 uint64_t *nr5g_fapi_fapi2mac_wls_get(
34 uint32_t * const msg_size,
35 uint16_t * const msg_type,
36 uint16_t * const flags);
38 uint8_t nr5g_fapi_fapi2mac_wls_put(
39 const p_fapi_api_queue_elem_t p_msg,
44 uint8_t nr5g_fapi_fapi2mac_wls_send(
45 const p_fapi_api_queue_elem_t p_list_elem,
48 //------------------------------------------------------------------------------
49 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
51 * @param data Pointer to validate
53 * @return TRUE If pointer is within valid shared WLS memory region
54 * FALSE If pointer is out of valid shared WLS memory region
57 * This function validates pointer's in WLS shared memory region
60 //------------------------------------------------------------------------------
61 uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
64 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
65 if ((unsigned long)data >= (unsigned long)p_wls_ctx->shmem &&
66 (unsigned long)data < ((unsigned long)p_wls_ctx->shmem +
67 p_wls_ctx->nPartitionMemSize)) {
74 //------------------------------------------------------------------------------
75 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
79 * @return A pointer to WLS_HANDLE stucture
82 * This function returns the WLS instance
85 //------------------------------------------------------------------------------
86 static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
89 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
91 return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
94 //------------------------------------------------------------------------------
95 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
99 * @return Pointer to the memory block
102 * This function allocates a block of memory from the pool
105 //------------------------------------------------------------------------------
106 void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
109 uint64_t pa_block = 0;
110 void *p_va_block = NULL;
111 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
112 WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
114 if (pthread_mutex_lock((pthread_mutex_t *) &
115 p_wls_ctx->fapi2mac_lock_alloc)) {
116 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
119 if (p_fapi2mac_buffers) {
120 p_va_block = (void *)p_fapi2mac_buffers;
121 p_fapi2mac_buffers = p_fapi2mac_buffers->p_next;
123 pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
125 if (pthread_mutex_unlock((pthread_mutex_t *) &
126 p_wls_ctx->fapi2mac_lock_alloc)) {
127 NR5G_FAPI_LOG(ERROR_LOG,
128 ("unable to unlock alloc pthread mutex"));
131 //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
134 p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
136 if (pthread_mutex_unlock((pthread_mutex_t *) &
137 p_wls_ctx->fapi2mac_lock_alloc)) {
138 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
144 //------------------------------------------------------------------------------
145 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
149 * @return Pointer to the memory block
152 * This function allocates a block of memory from the pool
155 //------------------------------------------------------------------------------
156 void nr5g_fapi_fapi2mac_wls_free_buffer(
159 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
161 if (pthread_mutex_lock((pthread_mutex_t *) &
162 p_wls_ctx->fapi2mac_lock_alloc)) {
163 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
166 if (p_fapi2mac_buffers) {
167 ((p_fapi_api_queue_elem_t) buffers)->p_next = p_fapi2mac_buffers;
168 p_fapi2mac_buffers = (p_fapi_api_queue_elem_t) buffers;
170 p_fapi2mac_buffers = (p_fapi_api_queue_elem_t) buffers;
171 p_fapi2mac_buffers->p_next = NULL;
174 if (pthread_mutex_unlock((pthread_mutex_t *) &
175 p_wls_ctx->fapi2mac_lock_alloc)) {
176 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
181 //------------------------------------------------------------------------------
182 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
186 * @return 0 if SUCCESS
189 * This function is called at WLS init and waits infinitely for L1 to respond back with some information
193 //------------------------------------------------------------------------------
194 uint8_t nr5g_fapi_fapi2mac_wls_ready(
198 ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
202 //------------------------------------------------------------------------------
203 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
207 * @return Number of blocks of APIs received
210 * This functions waits in an infinite loop for L1 to send a list of APIs to MAC. This is called
211 * during runtime when L2 sends API to L1 and then waits for a response back.
214 //------------------------------------------------------------------------------
215 uint32_t nr5g_fapi_fapi2mac_wls_wait(
219 // NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
220 ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
224 //------------------------------------------------------------------------------
225 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
227 * @param[out] data Location where First API from L1 is stored
229 * @return Size of Message sent from L1
232 * This function checks if this is the last message in this tti.
235 //------------------------------------------------------------------------------
236 static inline uint8_t is_msg_present(
239 return (!((flags & WLS_TF_FIN) || (flags == 0)));
242 //------------------------------------------------------------------------------
243 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
245 * @param[out] data Location where First API from L1 is stored
247 * @return Size of Message sent from L1
250 * This function queries the APIs sent from L1 to L2 and gets the first pointer
254 //------------------------------------------------------------------------------
255 uint64_t *nr5g_fapi_fapi2mac_wls_get(
256 uint32_t * const msg_size,
257 uint16_t * const msg_type,
258 uint16_t * const flags)
260 uint64_t *data = NULL;
263 uint16_t mt = 0, f = 0;
265 h_wls = nr5g_fapi_fapi2mac_wls_instance();
266 data = (uint64_t *) WLS_Get1(h_wls, &ms, &mt, &f);
267 *msg_size = ms, *msg_type = mt, *flags = f;
268 NR5G_FAPI_LOG(TRACE_LOG, ("[FAPI2MAC WLS][GET] %p size: %d "
269 "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
274 //------------------------------------------------------------------------------
275 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
277 * @param[in] ptr Pointer to the block to send
278 * @param[in] size Size of the block to send
280 * @return 0 if SUCCESS
283 * This function sends a single block of API from PHY to MAC
286 //------------------------------------------------------------------------------
287 inline uint8_t nr5g_fapi_fapi2mac_wls_put(
288 const p_fapi_api_queue_elem_t p_msg,
293 uint8_t ret = SUCCESS;
295 WLS_HANDLE h_mac_wls = nr5g_fapi_fapi2mac_wls_instance();
296 uint64_t pa = nr5g_fapi_wls_va_to_pa(h_mac_wls, (void *)p_msg);
297 NR5G_FAPI_LOG(TRACE_LOG, ("[FAPI2MAC WLS][PUT] %ld size: %d "
298 "type: %x flags: %x", pa, msg_size, msg_type, flags));
300 ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
305 //------------------------------------------------------------------------------
306 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
308 * @param[in] p_list Pointer to the linked list head
310 * @return 0 if SUCCESS
313 * This function sends a linked list of APIs from PHY to MAC.
316 //------------------------------------------------------------------------------
317 uint8_t nr5g_fapi_fapi2mac_wls_send(
318 const p_fapi_api_queue_elem_t p_list_elem,
321 uint8_t ret = SUCCESS;
322 p_fapi_api_queue_elem_t p_curr_msg = NULL;
323 fapi_msg_t *p_msg_header = NULL;
325 uint16_t flags_urllc = (is_urllc ? WLS_TF_URLLC : 0);
326 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
327 uint64_t start_tick = __rdtsc();
329 p_curr_msg = p_list_elem;
331 if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2mac_lock_send)) {
332 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
336 if (p_curr_msg && p_curr_msg->p_next) {
337 flags = WLS_SG_FIRST | flags_urllc;
338 if (p_curr_msg->msg_type == FAPI_VENDOR_MSG_HEADER_IND) {
339 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
340 p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
341 FAPI_VENDOR_MSG_HEADER_IND, flags)) {
343 if (pthread_mutex_unlock((pthread_mutex_t *) &
344 p_wls_ctx->fapi2mac_lock_send)) {
345 NR5G_FAPI_LOG(ERROR_LOG,
346 ("unable to unlock send pthread mutex"));
350 p_curr_msg = p_curr_msg->p_next;
351 flags = WLS_SG_NEXT | flags_urllc;
356 p_msg_header = (fapi_msg_t *) (p_curr_msg + 1);
357 if (p_curr_msg->p_next) { // FIRST/NEXT
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"));
369 p_curr_msg = p_curr_msg->p_next;
371 flags = WLS_SG_LAST | flags_urllc;
372 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
373 p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
374 p_msg_header->msg_id, flags)) {
376 if (pthread_mutex_unlock((pthread_mutex_t *) &
377 p_wls_ctx->fapi2mac_lock_send)) {
378 NR5G_FAPI_LOG(ERROR_LOG,
379 ("unable to unlock send pthread mutex"));
385 flags = WLS_SG_NEXT | flags_urllc;
389 if (pthread_mutex_unlock((pthread_mutex_t *) &
390 p_wls_ctx->fapi2mac_lock_send)) {
391 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
394 tick_total_wls_send_per_tti_ul += __rdtsc() - start_tick;
399 //------------------------------------------------------------------------------
400 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
402 * @param[out] data Location where First API from L1 is stored
404 * @return Size of Message sent from L1
407 * This function queries the APIs sent from L1 to L2 and gets the first pointer
411 //------------------------------------------------------------------------------
412 p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
415 uint16_t msg_type = 0;
417 uint32_t msg_size = 0;
418 uint32_t num_elms = 0;
419 uint64_t *p_msg = NULL;
420 p_fapi_api_queue_elem_t p_qelm_list = NULL, p_urllc_qelm_list = NULL;
421 p_fapi_api_queue_elem_t p_qelm = NULL;
422 p_fapi_api_queue_elem_t p_tail_qelm = NULL, p_urllc_tail_qelm = NULL;
423 WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
424 uint64_t start_tick = 0;
426 num_elms = nr5g_fapi_fapi2mac_wls_wait();
430 start_tick = __rdtsc();
432 p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
434 p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
436 if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
437 printf("Error: Invalid Ptr\n");
440 p_qelm->p_next = NULL;
442 if (flags & WLS_TF_URLLC)
444 if (p_urllc_qelm_list) {
445 p_urllc_tail_qelm = p_urllc_qelm_list;
446 while (NULL != p_urllc_tail_qelm->p_next) {
447 p_urllc_tail_qelm = p_urllc_tail_qelm->p_next;
449 p_urllc_tail_qelm->p_next = p_qelm;
451 p_urllc_qelm_list = p_qelm;
455 p_tail_qelm = p_qelm_list;
456 while (NULL != p_tail_qelm->p_next) {
457 p_tail_qelm = p_tail_qelm->p_next;
459 p_tail_qelm->p_next = p_qelm;
461 p_qelm_list = p_qelm;
466 } while (num_elms && is_msg_present(flags));
468 if (p_urllc_qelm_list) {
469 nr5g_fapi_urllc_thread_callback((void *) p_urllc_qelm_list,
470 &nr5g_fapi_get_nr5g_fapi_phy_ctx()->urllc_mac2phy_params);
473 tick_total_wls_get_per_tti_dl += __rdtsc() - start_tick;