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 //------------------------------------------------------------------------------
32 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
34 * @param data Pointer to validate
36 * @return TRUE If pointer is within valid shared WLS memory region
37 * FALSE If pointer is out of valid shared WLS memory region
40 * This function validates pointer's in WLS shared memory region
43 //------------------------------------------------------------------------------
44 uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
47 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
48 if ((unsigned long)data >= (unsigned long)p_wls_ctx->shmem &&
49 (unsigned long)data < ((unsigned long)p_wls_ctx->shmem +
50 p_wls_ctx->nPartitionMemSize)) {
57 //------------------------------------------------------------------------------
58 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
62 * @return A pointer to WLS_HANDLE stucture
65 * This function returns the WLS instance
68 //------------------------------------------------------------------------------
69 static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
72 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
74 return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
77 //------------------------------------------------------------------------------
78 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
82 * @return Pointer to the memory block
85 * This function allocates a block of memory from the pool
88 //------------------------------------------------------------------------------
89 void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
92 uint64_t pa_block = 0;
93 void *p_va_block = NULL;
94 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
95 WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
97 if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->
98 fapi2mac_lock_alloc)) {
99 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
102 pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
103 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
104 fapi2mac_lock_alloc)) {
105 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
110 //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
113 p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
117 //------------------------------------------------------------------------------
118 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
122 * @return 0 if SUCCESS
125 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
129 //------------------------------------------------------------------------------
130 uint8_t nr5g_fapi_fapi2mac_wls_ready(
134 ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
138 //------------------------------------------------------------------------------
139 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
143 * @return Number of blocks of APIs received
146 * This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
147 * during runtime when L2 sends a API to L1 and then waits for response back.
150 //------------------------------------------------------------------------------
151 uint8_t nr5g_fapi_fapi2mac_wls_wait(
155 // NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
156 ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
160 //------------------------------------------------------------------------------
161 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
163 * @param[out] data Location where First API from L1 is stored
165 * @return Size of Message sent from L1
168 * This function checks if this is the last message in this tti.
171 //------------------------------------------------------------------------------
172 static inline uint8_t is_msg_present(
175 return (!((flags & WLS_TF_FIN) || (flags == 0)));
178 //------------------------------------------------------------------------------
179 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
181 * @param[out] data Location where First API from L1 is stored
183 * @return Size of Message sent from L1
186 * This function queries the APIs sent from L1 to L2 and gets the first pointer
190 //------------------------------------------------------------------------------
191 uint64_t *nr5g_fapi_fapi2mac_wls_get(
196 uint64_t *data = NULL;
199 uint16_t mt = 0, f = 0;
201 h_wls = nr5g_fapi_fapi2mac_wls_instance();
202 data = (uint64_t *) WLS_Get1(h_wls, &ms, &mt, &f);
203 *msg_size = ms, *msg_type = mt, *flags = f;
204 NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][GET] %p size: %d "
205 "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
210 //------------------------------------------------------------------------------
211 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
213 * @param[in] ptr Pointer to the block to send
214 * @param[in] size Size of the block to send
216 * @return 0 if SUCCESS
219 * This function sends a single block of API from PHY to MAC
222 //------------------------------------------------------------------------------
223 inline uint8_t nr5g_fapi_fapi2mac_wls_put(
224 p_fapi_api_queue_elem_t p_msg,
229 uint8_t ret = SUCCESS;
231 WLS_HANDLE h_mac_wls = nr5g_fapi_fapi2mac_wls_instance();
232 uint64_t pa = nr5g_fapi_wls_va_to_pa(h_mac_wls, (void *)p_msg);
233 NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][PUT] %ld size: %d "
234 "type: %x flags: %x", pa, msg_size, msg_type, flags));
236 ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
241 //------------------------------------------------------------------------------
242 /** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
244 * @param[in] p_list Pointer to the linked list head
246 * @return 0 if SUCCESS
249 * This function sends a linked list of APIs from PHY to MAC.
252 //------------------------------------------------------------------------------
253 uint8_t nr5g_fapi_fapi2mac_wls_send(
254 p_fapi_api_queue_elem_t p_list_elem)
256 uint8_t ret = SUCCESS;
257 p_fapi_api_queue_elem_t p_curr_msg = NULL;
258 fapi_msg_t *p_msg_header = NULL;
260 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
262 p_curr_msg = p_list_elem;
264 if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2mac_lock_send)) {
265 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
269 if (p_curr_msg && p_curr_msg->p_next) {
270 flags = WLS_SG_FIRST;
271 if (p_curr_msg->msg_type == FAPI_MSG_HEADER_IND) {
272 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
273 p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
274 FAPI_MSG_HEADER_IND, flags)) {
276 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
277 fapi2mac_lock_send)) {
278 NR5G_FAPI_LOG(ERROR_LOG,
279 ("unable to unlock send pthread mutex"));
283 p_curr_msg = p_curr_msg->p_next;
289 p_msg_header = (fapi_msg_t *) (p_curr_msg + 1);
290 if (p_curr_msg->p_next) { // FIRST/NEXT
291 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
292 p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
293 p_msg_header->msg_id, flags)) {
295 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
296 fapi2mac_lock_send)) {
297 NR5G_FAPI_LOG(ERROR_LOG,
298 ("unable to unlock send pthread mutex"));
302 p_curr_msg = p_curr_msg->p_next;
305 if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
306 p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
307 p_msg_header->msg_id, flags)) {
309 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
310 fapi2mac_lock_send)) {
311 NR5G_FAPI_LOG(ERROR_LOG,
312 ("unable to unlock send pthread mutex"));
322 if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
323 fapi2mac_lock_send)) {
324 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
330 //------------------------------------------------------------------------------
331 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
333 * @param[out] data Location where First API from L1 is stored
335 * @return Size of Message sent from L1
338 * This function queries the APIs sent from L1 to L2 and gets the first pointer
342 //------------------------------------------------------------------------------
343 p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
346 uint16_t msg_type = 0;
348 uint32_t msg_size = 0;
349 uint32_t num_elms = 0;
350 uint64_t *p_msg = NULL;
351 p_fapi_api_queue_elem_t p_qelm_list = NULL;
352 p_fapi_api_queue_elem_t p_qelm = NULL;
353 p_fapi_api_queue_elem_t p_tail_qelm = NULL;
354 WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
356 num_elms = nr5g_fapi_fapi2mac_wls_wait();
361 p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
363 p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
365 if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
366 printf("Error: Invalid Ptr\n");
369 p_qelm->p_next = NULL;
371 p_tail_qelm = p_qelm_list;
372 while (NULL != p_tail_qelm->p_next) {
373 p_tail_qelm = p_tail_qelm->p_next;
375 p_tail_qelm->p_next = p_qelm;
377 p_qelm_list = p_qelm;
381 } while (num_elms && is_msg_present(flags));