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"
31 static p_fapi_api_queue_elem_t p_fapi2mac_buffers;
33 //------------------------------------------------------------------------------
34 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
36 * @param data Pointer to validate
38 * @return TRUE If pointer is within valid shared WLS memory region
39 * FALSE If pointer is out of valid shared WLS memory region
42 * This function validates pointer's in WLS shared memory region
45 //------------------------------------------------------------------------------
46 uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
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)) {
59 //------------------------------------------------------------------------------
60 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
64 * @return A pointer to WLS_HANDLE stucture
67 * This function returns the WLS instance
70 //------------------------------------------------------------------------------
71 static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
74 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
76 return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
79 //------------------------------------------------------------------------------
80 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
84 * @return Pointer to the memory block
87 * This function allocates a block of memory from the pool
90 //------------------------------------------------------------------------------
91 void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
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();
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"));
104 if (p_fapi2mac_buffers) {
105 p_va_block = (void *)p_fapi2mac_buffers;
106 p_fapi2mac_buffers = p_fapi2mac_buffers->p_next;
108 pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
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"));
116 //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
119 p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
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"));
129 //------------------------------------------------------------------------------
130 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
134 * @return Pointer to the memory block
137 * This function allocates a block of memory from the pool
140 //------------------------------------------------------------------------------
141 void nr5g_fapi_fapi2mac_wls_free_buffer(
144 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
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"));
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;
155 p_fapi2mac_buffers = (p_fapi_api_queue_elem_t) buffers;
156 p_fapi2mac_buffers->p_next = NULL;
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"));
166 //------------------------------------------------------------------------------
167 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
171 * @return 0 if SUCCESS
174 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
178 //------------------------------------------------------------------------------
179 uint8_t nr5g_fapi_fapi2mac_wls_ready(
183 ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
187 //------------------------------------------------------------------------------
188 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
192 * @return Number of blocks of APIs received
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.
199 //------------------------------------------------------------------------------
200 uint8_t nr5g_fapi_fapi2mac_wls_wait(
204 // NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
205 ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
209 //------------------------------------------------------------------------------
210 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
212 * @param[out] data Location where First API from L1 is stored
214 * @return Size of Message sent from L1
217 * This function checks if this is the last message in this tti.
220 //------------------------------------------------------------------------------
221 static inline uint8_t is_msg_present(
224 return (!((flags & WLS_TF_FIN) || (flags == 0)));
227 //------------------------------------------------------------------------------
228 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
230 * @param[out] data Location where First API from L1 is stored
232 * @return Size of Message sent from L1
235 * This function queries the APIs sent from L1 to L2 and gets the first pointer
239 //------------------------------------------------------------------------------
240 uint64_t *nr5g_fapi_fapi2mac_wls_get(
245 uint64_t *data = NULL;
248 uint16_t mt = 0, f = 0;
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));
259 //------------------------------------------------------------------------------
260 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
262 * @param[in] ptr Pointer to the block to send
263 * @param[in] size Size of the block to send
265 * @return 0 if SUCCESS
268 * This function sends a single block of API from PHY to MAC
271 //------------------------------------------------------------------------------
272 inline uint8_t nr5g_fapi_fapi2mac_wls_put(
273 p_fapi_api_queue_elem_t p_msg,
278 uint8_t ret = SUCCESS;
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));
285 ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
290 //------------------------------------------------------------------------------
291 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
293 * @param[in] p_list Pointer to the linked list head
295 * @return 0 if SUCCESS
298 * This function sends a linked list of APIs from PHY to MAC.
301 //------------------------------------------------------------------------------
302 uint8_t nr5g_fapi_fapi2mac_wls_send(
303 p_fapi_api_queue_elem_t p_list_elem)
305 uint8_t ret = SUCCESS;
306 p_fapi_api_queue_elem_t p_curr_msg = NULL;
307 fapi_msg_t *p_msg_header = NULL;
309 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
310 uint64_t start_tick = __rdtsc();
312 p_curr_msg = p_list_elem;
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"));
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)) {
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"));
333 p_curr_msg = p_curr_msg->p_next;
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)) {
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"));
352 p_curr_msg = p_curr_msg->p_next;
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)) {
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"));
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"));
377 tick_total_wls_send_per_tti_ul += __rdtsc() - start_tick;
382 //------------------------------------------------------------------------------
383 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
385 * @param[out] data Location where First API from L1 is stored
387 * @return Size of Message sent from L1
390 * This function queries the APIs sent from L1 to L2 and gets the first pointer
394 //------------------------------------------------------------------------------
395 p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
398 uint16_t msg_type = 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;
409 num_elms = nr5g_fapi_fapi2mac_wls_wait();
413 start_tick = __rdtsc();
415 p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
417 p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
419 if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
420 printf("Error: Invalid Ptr\n");
423 p_qelm->p_next = NULL;
425 p_tail_qelm = p_qelm_list;
426 while (NULL != p_tail_qelm->p_next) {
427 p_tail_qelm = p_tail_qelm->p_next;
429 p_tail_qelm->p_next = p_qelm;
431 p_qelm_list = p_qelm;
435 } while (num_elms && is_msg_present(flags));
436 tick_total_wls_get_per_tti_dl += __rdtsc() - start_tick;