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 PHY
21 * @defgroup nr5g_fapi_source_framework_wls_lib_group
24 #include "nr5g_fapi_framework.h"
25 #include "nr5g_fapi_internal.h"
26 #include "nr5g_fapi_wls.h"
27 #include "nr5g_fapi_config_loader.h"
28 #include "nr5g_fapi_log.h"
29 #include "nr5g_fapi_memory.h"
31 #define WLS_HUGE_DEF_PAGE_SIZEA 0x40000000LL
33 nr5g_fapi_wls_context_t g_wls_ctx;
35 static uint8_t alloc_track[ALLOC_TRACK_SIZE];
37 //------------------------------------------------------------------------------
38 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
42 * @return A pointer to WLS Context stucture
45 * This function returns the WLS Context structure which has WLS related parameters
48 //------------------------------------------------------------------------------
49 inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context(
55 //----------------------------------------------------------------------------------
56 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
60 * @return 0 if SUCCESS
63 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
67 //----------------------------------------------------------------------------------
68 inline uint8_t nr5g_fapi_fapi2phy_wls_ready(
72 p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
74 retval = WLS_Ready(p_wls->h_wls[NR5G_FAPI2PHY_WLS_INST]);
79 //----------------------------------------------------------------------------------
80 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
84 * @return 0 if SUCCESS
87 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
91 //----------------------------------------------------------------------------------
92 inline uint8_t nr5g_fapi_fapi2mac_wls_ready(
96 p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
98 retval = WLS_Ready1(p_wls->h_wls[NR5G_FAPI2MAC_WLS_INST]);
103 //------------------------------------------------------------------------------
104 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
106 * @param[in] ptr Pointer to display
107 * @param[in] size Size of data
112 * This function displays content of Buffer - Used for debugging
115 //------------------------------------------------------------------------------
116 void nr5g_fapi_wls_show_data(
123 for (i = 0; i < size; i++) {
126 printf("%02x ", d[i]);
131 //------------------------------------------------------------------------------
132 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
139 * This function prints to the console FAPI stats
142 //------------------------------------------------------------------------------
143 void nr5g_fapi_wls_print_stats(
146 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
147 printf(" nTotalBlocks[%5d] nAllocBlocks[%5d] nFreeBlocks[%5d]\n",
148 pWls->nTotalBlocks, pWls->nAllocBlocks,
149 (pWls->nTotalBlocks - pWls->nAllocBlocks));
150 printf(" nTotalAllocCnt[%5d] nTotalFreeCnt[%5d] Diff[%5d]\n",
151 pWls->nTotalAllocCnt, pWls->nTotalFreeCnt,
152 (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt));
153 uint32_t nFinalTotalDlBufAllocCnt = 0, nFinalTotalDlBufFreeCnt = 0, idx;
155 //#define PRINTF_DEBUG(fmt, args...) //printf(fmt, ## args)
156 #define PRINTF_DEBUG(fmt, args...)
158 PRINTF_DEBUG("\n nDlBufAllocCnt: \n");
159 for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
160 nFinalTotalDlBufAllocCnt += pWls->nTotalDlBufAllocCnt[idx];
161 PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufAllocCnt[idx]);
164 PRINTF_DEBUG("\n nDlBufFreeCnt: \n");
165 for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
166 nFinalTotalDlBufFreeCnt += pWls->nTotalDlBufFreeCnt[idx];
167 PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufFreeCnt[idx]);
169 PRINTF_DEBUG("\n\n");
171 printf(" nDlBufAllocCnt[%5d] nDlBufFreeCnt[%5d] Diff[%5d]\n",
172 nFinalTotalDlBufAllocCnt, nFinalTotalDlBufFreeCnt,
173 (nFinalTotalDlBufAllocCnt - nFinalTotalDlBufFreeCnt));
175 (" nUlBufAllocCnt[%5d] nUlBufFreeCnt[%5d] Diff[%5d]\n\n",
176 pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt,
177 (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt));
180 //------------------------------------------------------------------------------
181 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
183 * @param[in] ptr Address to convert
185 * @return Converted address
188 * This function converts Virtual Address to Physical Address
191 //------------------------------------------------------------------------------
192 uint64_t nr5g_fapi_wls_va_to_pa(
196 return ((uint64_t) WLS_VA2PA(h_wls, ptr));
199 //------------------------------------------------------------------------------
200 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
202 * @param[in] ptr Address to convert
204 * @return Converted address
207 * This function converts Physical Address to Virtual Address
210 //------------------------------------------------------------------------------
211 void *nr5g_fapi_wls_pa_to_va(
215 return ((void *)WLS_PA2VA(h_wls, ptr));
218 //------------------------------------------------------------------------------
219 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
223 * @return Number of blocks added
226 * This function add WLS blocks to the L1 Array which will be used by L1 in
227 * every TTI to populate and send back APIs to the MAC
230 //------------------------------------------------------------------------------
231 uint32_t wls_fapi_add_blocks_to_ul(
234 uint32_t num_blocks = 0;
235 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
236 WLS_HANDLE h_wls = pWls->h_wls[NR5G_FAPI2PHY_WLS_INST];
238 void *pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
243 /* allocate blocks for UL transmittion */
244 while (WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls, pMsg)) > 0) {
246 pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
251 // free not enqueued block
253 wls_fapi_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS);
259 //------------------------------------------------------------------------------
260 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
262 * @param A pointer to the phy instance table.
264 * @return 0 if SUCCESS
266 * @description This function initializes WLS layer primitives and allocates
267 * memory needed to exchange APIs between FAPI and PHY.
269 //------------------------------------------------------------------------------
270 uint8_t nr5g_fapi_wls_init(
271 p_nr5g_fapi_cfg_t cfg)
273 uint64_t mac_shmem_size = 0;
274 uint64_t phy_shmem_size = 0;
276 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
278 if (p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST] &&
279 p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]) {
280 // NR5G_FAPI_LOG(ERROR_LOG, ("WLS instance already opened!"));
284 p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] =
285 WLS_Open_Dual(basename(cfg->wls.device_name), WLS_SLAVE_CLIENT,
286 &mac_shmem_size, &phy_shmem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]);
288 cfg->wls.shmem_size = mac_shmem_size + phy_shmem_size;
289 p_wls_ctx->shmem_size = cfg->wls.shmem_size;
290 if ((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) &&
291 (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST])) {
292 NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI_ WLS] WLS Open Dual Failed."));
295 // Issue WLS_Alloc() for FAPI2MAC
296 p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST],
297 p_wls_ctx->shmem_size);
299 if (NULL == p_wls_ctx->shmem) {
300 printf("Unable to alloc WLS Memory for FAPI2MAC\n");
304 p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST],
305 p_wls_ctx->shmem_size);
306 p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem;
307 p_wls_ctx->nTotalMemorySize = mac_shmem_size;
308 if (NULL == p_wls_ctx->shmem) {
309 printf("Unable to alloc WLS Memory\n");
312 // Now the L2 is up so let's make sure that the L1 was started first
314 // First let's wait for the L1 and L2 to be present
315 while (nr5g_fapi_fapi2phy_wls_ready()) ;
316 NR5G_FAPI_LOG(INFO_LOG, ("L1 is up..."));
317 // Now the L2 is up so let's make sure that the L1 was started first
318 while (nr5g_fapi_fapi2mac_wls_ready()) ;
319 NR5G_FAPI_LOG(INFO_LOG, ("L2 is up..."));
321 // Now that the L2 is up and has completed the Common Memory initialization
323 if (FAILURE == nr5g_fapi_wls_memory_init()) {
327 pthread_mutex_init((pthread_mutex_t *)
328 & p_wls_ctx->fapi2phy_lock_send, NULL);
329 pthread_mutex_init((pthread_mutex_t *)
330 & p_wls_ctx->fapi2phy_lock_alloc, NULL);
331 pthread_mutex_init((pthread_mutex_t *)
332 & p_wls_ctx->fapi2mac_lock_send, NULL);
333 pthread_mutex_init((pthread_mutex_t *)
334 & p_wls_ctx->fapi2mac_lock_alloc, NULL);
338 //-------------------------------------------------------------------------------------------
339 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
341 * @param[in] pMemArray Pointer to WLS Memory Management Structure
342 * @param[in] pMemArrayMmeory pointer to flat buffer that was allocated
343 * @param[in] totalSize total size of flat buffer allocated
344 * @param[in] nBlockSize Size of each block that needs to be partitoned by the memory manager
346 * @return 0 if SUCCESS
349 * This function creates memory blocks from a flat buffer which will be used for communication between FAPI and PHY
352 //-------------------------------------------------------------------------------------------
353 uint32_t wls_fapi_create_mem_array(
354 PWLS_FAPI_MEM_STRUCT pMemArray,
355 void *pMemArrayMemory,
360 int numBlocks = totalSize / nBlockSize;
365 ("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
366 pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
368 // Can't be less than pointer size
369 if (nBlockSize < sizeof(void *)) {
372 // Can't be less than one block
373 if (totalSize < sizeof(void *)) {
377 pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
378 pMemArray->pStorage = pMemArrayMemory;
379 pMemArray->pEndOfStorage =
380 ((unsigned long *)pMemArrayMemory) +
381 numBlocks * nBlockSize / sizeof(unsigned long);
382 pMemArray->nBlockSize = nBlockSize;
383 pMemArray->nBlockCount = numBlocks;
385 // Initialize single-linked list of free blocks;
386 ptr = (void **)pMemArrayMemory;
387 for (i = 0; i < pMemArray->nBlockCount; i++) {
388 #ifdef MEMORY_CORRUPTION_DETECT
389 // Fill with some pattern
390 uint8_t *p = (uint8_t *) ptr;
393 p += (nBlockSize - 16);
394 for (j = 0; j < 16; j++) {
395 p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
399 if (i == pMemArray->nBlockCount - 1) {
400 *ptr = NULL; // End of list
402 // Points to the next block
403 *ptr = (void **)(((uint8_t *) ptr) + nBlockSize);
404 ptr += nBlockSize / sizeof(unsigned long);
408 NR5G_FAPI_MEMSET(alloc_track, sizeof(uint8_t) * ALLOC_TRACK_SIZE, 0,
409 sizeof(uint8_t) * ALLOC_TRACK_SIZE);
414 //-------------------------------------------------------------------------------------------
415 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
417 * @param[in] pWls Pointer to the nr5g_fapi_wls_ctx structure
419 * @return 0 if SUCCESS
422 * This function created a partition and blocks of WLS memory for API exchange between FAPI and PHY
425 //-------------------------------------------------------------------------------------------
426 uint8_t wls_fapi_create_partition(
427 p_nr5g_fapi_wls_context_t pWls)
429 uint64_t nWlsMemBaseUsable;
430 uint64_t nTotalMemorySizeUsable;
431 uint64_t nBalance, nBlockSize, nBlockSizeMask, nHugepageSizeMask;
433 nBlockSize = MSG_MAXSIZE;
434 nWlsMemBaseUsable = (uint64_t)pWls->pWlsMemBase;
435 nTotalMemorySizeUsable = pWls->nTotalMemorySize - WLS_HUGE_DEF_PAGE_SIZEA;
436 nBlockSizeMask = nBlockSize-1;
438 // Align Starting Location
439 nWlsMemBaseUsable = (nWlsMemBaseUsable + nBlockSizeMask) & (~nBlockSizeMask);
440 nBalance = nWlsMemBaseUsable - (uint64_t)pWls->pWlsMemBase;
441 nTotalMemorySizeUsable -= nBalance;
443 // Align Ending Location
444 nBalance = nTotalMemorySizeUsable % nBlockSize;
445 nTotalMemorySizeUsable -= nBalance;
447 // Move start location to the next hugepage boundary
448 nHugepageSizeMask = WLS_HUGE_DEF_PAGE_SIZEA-1;
449 nWlsMemBaseUsable = (nWlsMemBaseUsable + WLS_HUGE_DEF_PAGE_SIZEA) & (~nHugepageSizeMask);
452 pWls->pPartitionMemBase = (void *)nWlsMemBaseUsable;
453 pWls->nPartitionMemSize = nTotalMemorySizeUsable;
454 pWls->nTotalBlocks = pWls->nPartitionMemSize / nBlockSize;
455 return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase,
456 pWls->nPartitionMemSize, nBlockSize);
459 //------------------------------------------------------------------------------
460 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
462 * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2)
463 * @param[out] ppBlock Pointer where the allocated memory block is stored
465 * @return 0 if SUCCESS
467 * @description This function allocates a memory block from the pool
470 //------------------------------------------------------------------------------
471 uint32_t wls_fapi_alloc_mem_array(
472 PWLS_FAPI_MEM_STRUCT pMemArray,
477 if (pMemArray->ppFreeBlock == NULL) {
478 printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
481 // FIXME: Remove after debugging
482 if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) ||
483 ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) {
485 ("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
486 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
490 pMemArray->ppFreeBlock =
491 (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
492 *pMemArray->ppFreeBlock =
493 (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
495 if ((*pMemArray->ppFreeBlock != NULL) &&
496 (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
497 ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) {
499 "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
500 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
501 *pMemArray->ppFreeBlock);
505 *ppBlock = (void *)pMemArray->ppFreeBlock;
506 pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock);
509 (((uint64_t) * ppBlock -
510 (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
511 if (alloc_track[idx]) {
513 ("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
514 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
515 *pMemArray->ppFreeBlock);
518 #ifdef MEMORY_CORRUPTION_DETECT
519 uint32_t nBlockSize = pMemArray->nBlockSize, i;
520 uint8_t *p = (uint8_t *) * ppBlock;
522 p += (nBlockSize - 16);
523 for (i = 0; i < 16; i++) {
524 p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
527 alloc_track[idx] = 1;
530 //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
535 //------------------------------------------------------------------------------
536 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
538 * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2)
539 * @param[in] pBlock Pointer where the allocated memory block is stored
541 * @return 0 if SUCCESS
543 * @description This function frees a WLS block of memory and adds
544 * it back to the pool
547 //------------------------------------------------------------------------------
548 uint32_t wls_fapi_free_mem_array(
549 PWLS_FAPI_MEM_STRUCT pMemArray,
553 unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
555 pBlock = (void *)((unsigned long)pBlock & ~mask);
557 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
559 ("wls_fapi_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
560 pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
565 (int)(((uint64_t) pBlock -
566 (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
568 if (alloc_track[idx] == 0) {
570 ("wls_fapi_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
571 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, pBlock);
574 #ifdef MEMORY_CORRUPTION_DETECT
575 uint32_t nBlockSize = pMemArray->nBlockSize, i;
576 uint8_t *p = (uint8_t *) pBlock;
578 p += (nBlockSize - 16);
579 for (i = 0; i < 16; i++) {
580 if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG) {
581 printf("ERROR: Corruption\n");
582 nr5g_fapi_wls_print_stats();
587 alloc_track[idx] = 0;
590 if (((void *)pMemArray->ppFreeBlock) == pBlock) {
591 // Simple protection against freeing of already freed block
594 // FIXME: Remove after debugging
595 if ((pMemArray->ppFreeBlock != NULL)
596 && (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage)
597 || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))) {
599 ("wls_fapi_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
600 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
603 // FIXME: Remove after debugging
604 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
605 printf("wls_fapi_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
611 (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
612 pMemArray->ppFreeBlock =
613 (void **)((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
615 //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
620 //------------------------------------------------------------------------------
621 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
623 * @param size (if 0 fixed size from pool)
624 * @param Number of locations
626 * @return 0 if SUCCESS
628 * @description This function initializes WLS layer primitives and allocates
629 * memory needed to exchange APIs between FAPI and PHY.
631 //------------------------------------------------------------------------------
632 void *wls_fapi_alloc_buffer(
637 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
639 if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
640 NR5G_FAPI_LOG(ERROR_LOG, ("unable to get lock alloc pthread mutex"));
644 if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS) {
645 printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size,
647 nr5g_fapi_wls_print_stats();
650 pWls->nAllocBlocks++;
653 //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
655 //printf("[%p]\n", pBlock);
657 pWls->nTotalAllocCnt++;
658 if (loc < MAX_DL_BUF_LOCATIONS)
659 pWls->nTotalDlBufAllocCnt[loc]++;
660 else if (loc < MAX_UL_BUF_LOCATIONS)
661 pWls->nTotalUlBufAllocCnt++;
663 if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
664 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
671 //------------------------------------------------------------------------------
672 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
674 * @param[in] *pMsg Pointer to free
678 * @descriptioni This function frees a block of memory and adds it back to
682 //------------------------------------------------------------------------------
683 void wls_fapi_free_buffer(
687 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
689 if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
690 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
693 //printf("----------------wls_fapi_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
694 if (wls_fapi_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS) {
695 pWls->nAllocBlocks--;
697 printf("wls_fapi_free_buffer Free error\n");
698 nr5g_fapi_wls_print_stats();
702 pWls->nTotalFreeCnt++;
703 if (loc < MAX_DL_BUF_LOCATIONS)
704 pWls->nTotalDlBufFreeCnt[loc]++;
705 else if (loc < MAX_UL_BUF_LOCATIONS)
706 pWls->nTotalUlBufFreeCnt++;
708 if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
709 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
714 //------------------------------------------------------------------------------
715 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
717 * @param A pointer to a wls instance
719 * @return 0 if SUCCESS
721 * @description This function initializes the WLS layer FAPI2PHY interface
722 * primitives and allocates memory needed to exchange APIs
723 * between FAPI and PHY.
725 //------------------------------------------------------------------------------
726 uint8_t nr5g_fapi_wls_memory_init(
729 uint32_t nBlocks = 0;
730 p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
732 if (FAILURE == wls_fapi_create_partition(p_wls))
735 if ((nBlocks = wls_fapi_add_blocks_to_ul()) == 0) {
736 NR5G_FAPI_LOG(ERROR_LOG, ("Unable to allocate blocks to PHY"));