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 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_lib_group
82 * @param[in] ptr Pointer to display
83 * @param[in] size Size of data
88 * This function displays content of Buffer - Used for debugging
91 //------------------------------------------------------------------------------
92 void nr5g_fapi_wls_show_data(
99 for (i = 0; i < size; i++) {
102 printf("%02x ", d[i]);
107 //------------------------------------------------------------------------------
108 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
115 * This function prints to the console FAPI stats
118 //------------------------------------------------------------------------------
119 void nr5g_fapi_wls_print_stats(
122 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
123 printf(" nTotalBlocks[%5d] nAllocBlocks[%5d] nFreeBlocks[%5d]\n",
124 pWls->nTotalBlocks, pWls->nAllocBlocks,
125 (pWls->nTotalBlocks - pWls->nAllocBlocks));
126 printf(" nTotalAllocCnt[%5d] nTotalFreeCnt[%5d] Diff[%5d]\n",
127 pWls->nTotalAllocCnt, pWls->nTotalFreeCnt,
128 (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt));
129 uint32_t nFinalTotalDlBufAllocCnt = 0, nFinalTotalDlBufFreeCnt = 0, idx;
131 //#define PRINTF_DEBUG(fmt, args...) //printf(fmt, ## args)
132 #define PRINTF_DEBUG(fmt, args...)
134 PRINTF_DEBUG("\n nDlBufAllocCnt: \n");
135 for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
136 nFinalTotalDlBufAllocCnt += pWls->nTotalDlBufAllocCnt[idx];
137 PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufAllocCnt[idx]);
140 PRINTF_DEBUG("\n nDlBufFreeCnt: \n");
141 for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
142 nFinalTotalDlBufFreeCnt += pWls->nTotalDlBufFreeCnt[idx];
143 PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufFreeCnt[idx]);
145 PRINTF_DEBUG("\n\n");
147 printf(" nDlBufAllocCnt[%5d] nDlBufFreeCnt[%5d] Diff[%5d]\n",
148 nFinalTotalDlBufAllocCnt, nFinalTotalDlBufFreeCnt,
149 (nFinalTotalDlBufAllocCnt - nFinalTotalDlBufFreeCnt));
151 (" nUlBufAllocCnt[%5d] nUlBufFreeCnt[%5d] Diff[%5d]\n\n",
152 pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt,
153 (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt));
156 //------------------------------------------------------------------------------
157 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
159 * @param[in] ptr Address to convert
161 * @return Converted address
164 * This function converts Virtual Address to Physical Address
167 //------------------------------------------------------------------------------
168 uint64_t nr5g_fapi_wls_va_to_pa(
172 return ((uint64_t) WLS_VA2PA(h_wls, ptr));
175 //------------------------------------------------------------------------------
176 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
178 * @param[in] ptr Address to convert
180 * @return Converted address
183 * This function converts Physical Address to Virtual Address
186 //------------------------------------------------------------------------------
187 void *nr5g_fapi_wls_pa_to_va(
191 return ((void *)WLS_PA2VA(h_wls, ptr));
194 //------------------------------------------------------------------------------
195 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
199 * @return Number of blocks added
202 * This function add WLS blocks to the L1 Array which will be used by L1 in
203 * every TTI to populate and send back APIs to the MAC
206 //------------------------------------------------------------------------------
207 uint32_t wls_fapi_add_blocks_to_ul(
210 uint32_t num_blocks = 0;
211 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
212 WLS_HANDLE h_wls = pWls->h_wls[NR5G_FAPI2PHY_WLS_INST];
214 void *pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
219 /* allocate blocks for UL transmittion */
220 while (WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls, pMsg)) > 0) {
222 pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
227 // free not enqueued block
229 wls_fapi_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS);
235 //------------------------------------------------------------------------------
236 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
238 * @param A pointer to the phy instance table.
240 * @return 0 if SUCCESS
242 * @description This function initializes WLS layer primitives and allocates
243 * memory needed to exchange APIs between FAPI and PHY.
245 //------------------------------------------------------------------------------
246 uint8_t nr5g_fapi_wls_init(
247 p_nr5g_fapi_cfg_t cfg)
249 uint64_t mac_shmem_size = 0;
250 uint64_t phy_shmem_size = 0;
252 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
254 if (p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST] &&
255 p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]) {
256 // NR5G_FAPI_LOG(ERROR_LOG, ("WLS instance already opened!"));
260 p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] =
261 WLS_Open_Dual(basename(cfg->wls.device_name), WLS_SLAVE_CLIENT,
262 &mac_shmem_size, &phy_shmem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]);
264 cfg->wls.shmem_size = mac_shmem_size + phy_shmem_size;
265 p_wls_ctx->shmem_size = cfg->wls.shmem_size;
266 if ((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) &&
267 (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST])) {
268 NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI_ WLS] WLS Open Dual Failed."));
271 // Issue WLS_Alloc() for FAPI2MAC
272 p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST],
273 p_wls_ctx->shmem_size);
275 if (NULL == p_wls_ctx->shmem) {
276 printf("Unable to alloc WLS Memory for FAPI2MAC\n");
280 p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST],
281 p_wls_ctx->shmem_size);
282 p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem;
283 p_wls_ctx->nTotalMemorySize = mac_shmem_size;
284 if (NULL == p_wls_ctx->shmem) {
285 printf("Unable to alloc WLS Memory\n");
288 // Now the L2 is up so let's make sure that the L1 was started first
290 // First let's wait for the L1 and L2 to be present
291 while (nr5g_fapi_fapi2phy_wls_ready()) ;
292 NR5G_FAPI_LOG(INFO_LOG, ("L1 is up..."));
293 // Now the L2 is up so let's make sure that the L1 was started first
294 while (nr5g_fapi_fapi2mac_wls_ready()) ;
295 NR5G_FAPI_LOG(INFO_LOG, ("L2 is up..."));
297 // Now that the L2 is up and has completed the Common Memory initialization
299 if (FAILURE == nr5g_fapi_wls_memory_init()) {
303 pthread_mutex_init((pthread_mutex_t *)
304 & p_wls_ctx->fapi2phy_lock_send, NULL);
305 pthread_mutex_init((pthread_mutex_t *)
306 & p_wls_ctx->fapi2phy_lock_alloc, NULL);
307 pthread_mutex_init((pthread_mutex_t *)
308 & p_wls_ctx->fapi2mac_lock_send, NULL);
309 pthread_mutex_init((pthread_mutex_t *)
310 & p_wls_ctx->fapi2mac_lock_alloc, NULL);
314 //-------------------------------------------------------------------------------------------
315 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
317 * @param[in] pMemArray Pointer to WLS Memory Management Structure
318 * @param[in] pMemArrayMmeory pointer to flat buffer that was allocated
319 * @param[in] totalSize total size of flat buffer allocated
320 * @param[in] nBlockSize Size of each block that needs to be partitoned by the memory manager
322 * @return 0 if SUCCESS
325 * This function creates memory blocks from a flat buffer which will be used for communication between FAPI and PHY
328 //-------------------------------------------------------------------------------------------
329 uint32_t wls_fapi_create_mem_array(
330 PWLS_FAPI_MEM_STRUCT pMemArray,
331 void *pMemArrayMemory,
336 int numBlocks = totalSize / nBlockSize;
341 ("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
342 pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
344 // Can't be less than pointer size
345 if (nBlockSize < sizeof(void *)) {
348 // Can't be less than one block
349 if (totalSize < sizeof(void *)) {
353 pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
354 pMemArray->pStorage = pMemArrayMemory;
355 pMemArray->pEndOfStorage =
356 ((unsigned long *)pMemArrayMemory) +
357 numBlocks * nBlockSize / sizeof(unsigned long);
358 pMemArray->nBlockSize = nBlockSize;
359 pMemArray->nBlockCount = numBlocks;
361 // Initialize single-linked list of free blocks;
362 ptr = (void **)pMemArrayMemory;
363 for (i = 0; i < pMemArray->nBlockCount; i++) {
364 #ifdef MEMORY_CORRUPTION_DETECT
365 // Fill with some pattern
366 uint8_t *p = (uint8_t *) ptr;
369 p += (nBlockSize - 16);
370 for (j = 0; j < 16; j++) {
371 p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
375 if (i == pMemArray->nBlockCount - 1) {
376 *ptr = NULL; // End of list
378 // Points to the next block
379 *ptr = (void **)(((uint8_t *) ptr) + nBlockSize);
380 ptr += nBlockSize / sizeof(unsigned long);
384 NR5G_FAPI_MEMSET(alloc_track, sizeof(uint8_t) * ALLOC_TRACK_SIZE, 0,
385 sizeof(uint8_t) * ALLOC_TRACK_SIZE);
390 //-------------------------------------------------------------------------------------------
391 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
393 * @param[in] pWls Pointer to the nr5g_fapi_wls_ctx structure
395 * @return 0 if SUCCESS
398 * This function created a partition and blocks of WLS memory for API exchange between FAPI and PHY
401 //-------------------------------------------------------------------------------------------
402 uint8_t wls_fapi_create_partition(
403 p_nr5g_fapi_wls_context_t pWls)
405 uint64_t nWlsMemBaseUsable;
406 uint64_t nTotalMemorySizeUsable;
407 uint64_t nBalance, nBlockSize, nBlockSizeMask, nHugepageSizeMask;
409 nBlockSize = MSG_MAXSIZE;
410 nWlsMemBaseUsable = (uint64_t)pWls->pWlsMemBase;
411 nTotalMemorySizeUsable = pWls->nTotalMemorySize - WLS_HUGE_DEF_PAGE_SIZEA;
412 nBlockSizeMask = nBlockSize-1;
414 // Align Starting Location
415 nWlsMemBaseUsable = (nWlsMemBaseUsable + nBlockSizeMask) & (~nBlockSizeMask);
416 nBalance = nWlsMemBaseUsable - (uint64_t)pWls->pWlsMemBase;
417 nTotalMemorySizeUsable -= nBalance;
419 // Align Ending Location
420 nBalance = nTotalMemorySizeUsable % nBlockSize;
421 nTotalMemorySizeUsable -= nBalance;
423 // Move start location to the next hugepage boundary
424 nHugepageSizeMask = WLS_HUGE_DEF_PAGE_SIZEA-1;
425 nWlsMemBaseUsable = (nWlsMemBaseUsable + WLS_HUGE_DEF_PAGE_SIZEA) & (~nHugepageSizeMask);
428 pWls->pPartitionMemBase = (void *)nWlsMemBaseUsable;
429 pWls->nPartitionMemSize = nTotalMemorySizeUsable;
430 pWls->nTotalBlocks = pWls->nPartitionMemSize / nBlockSize;
431 return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase,
432 pWls->nPartitionMemSize, nBlockSize);
435 //------------------------------------------------------------------------------
436 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
438 * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2)
439 * @param[out] ppBlock Pointer where the allocated memory block is stored
441 * @return 0 if SUCCESS
443 * @description This function allocates a memory block from the pool
446 //------------------------------------------------------------------------------
447 uint32_t wls_fapi_alloc_mem_array(
448 PWLS_FAPI_MEM_STRUCT pMemArray,
453 if (pMemArray->ppFreeBlock == NULL) {
454 printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
457 // FIXME: Remove after debugging
458 if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) ||
459 ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) {
461 ("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
462 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
466 pMemArray->ppFreeBlock =
467 (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
468 *pMemArray->ppFreeBlock =
469 (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
471 if ((*pMemArray->ppFreeBlock != NULL) &&
472 (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
473 ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) {
475 "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
476 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
477 *pMemArray->ppFreeBlock);
481 *ppBlock = (void *)pMemArray->ppFreeBlock;
482 pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock);
485 (((uint64_t) * ppBlock -
486 (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
487 if (alloc_track[idx]) {
489 ("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
490 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
491 *pMemArray->ppFreeBlock);
494 #ifdef MEMORY_CORRUPTION_DETECT
495 uint32_t nBlockSize = pMemArray->nBlockSize, i;
496 uint8_t *p = (uint8_t *) * ppBlock;
498 p += (nBlockSize - 16);
499 for (i = 0; i < 16; i++) {
500 p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
503 alloc_track[idx] = 1;
506 //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
511 //------------------------------------------------------------------------------
512 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
514 * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2)
515 * @param[in] pBlock Pointer where the allocated memory block is stored
517 * @return 0 if SUCCESS
519 * @description This function frees a WLS block of memory and adds
520 * it back to the pool
523 //------------------------------------------------------------------------------
524 uint32_t wls_fapi_free_mem_array(
525 PWLS_FAPI_MEM_STRUCT pMemArray,
529 unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
531 pBlock = (void *)((unsigned long)pBlock & ~mask);
533 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
535 ("wls_fapi_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
536 pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
541 (int)(((uint64_t) pBlock -
542 (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
544 if (alloc_track[idx] == 0) {
546 ("wls_fapi_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
547 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, pBlock);
550 #ifdef MEMORY_CORRUPTION_DETECT
551 uint32_t nBlockSize = pMemArray->nBlockSize, i;
552 uint8_t *p = (uint8_t *) pBlock;
554 p += (nBlockSize - 16);
555 for (i = 0; i < 16; i++) {
556 if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG) {
557 printf("ERROR: Corruption\n");
558 nr5g_fapi_wls_print_stats();
563 alloc_track[idx] = 0;
566 if (((void *)pMemArray->ppFreeBlock) == pBlock) {
567 // Simple protection against freeing of already freed block
570 // FIXME: Remove after debugging
571 if ((pMemArray->ppFreeBlock != NULL)
572 && (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage)
573 || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))) {
575 ("wls_fapi_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
576 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
579 // FIXME: Remove after debugging
580 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
581 printf("wls_fapi_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
587 (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
588 pMemArray->ppFreeBlock =
589 (void **)((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
591 //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
596 //------------------------------------------------------------------------------
597 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
599 * @param size (if 0 fixed size from pool)
600 * @param Number of locations
602 * @return 0 if SUCCESS
604 * @description This function initializes WLS layer primitives and allocates
605 * memory needed to exchange APIs between FAPI and PHY.
607 //------------------------------------------------------------------------------
608 void *wls_fapi_alloc_buffer(
613 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
615 if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
616 NR5G_FAPI_LOG(ERROR_LOG, ("unable to get lock alloc pthread mutex"));
620 if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS) {
621 printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size,
623 nr5g_fapi_wls_print_stats();
626 pWls->nAllocBlocks++;
629 //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
631 //printf("[%p]\n", pBlock);
633 pWls->nTotalAllocCnt++;
634 if (loc < MAX_DL_BUF_LOCATIONS)
635 pWls->nTotalDlBufAllocCnt[loc]++;
636 else if (loc < MAX_UL_BUF_LOCATIONS)
637 pWls->nTotalUlBufAllocCnt++;
639 if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
640 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
647 //------------------------------------------------------------------------------
648 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
650 * @param[in] *pMsg Pointer to free
654 * @descriptioni This function frees a block of memory and adds it back to
658 //------------------------------------------------------------------------------
659 void wls_fapi_free_buffer(
663 p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
665 if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
666 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
669 //printf("----------------wls_fapi_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
670 if (wls_fapi_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS) {
671 pWls->nAllocBlocks--;
673 printf("wls_fapi_free_buffer Free error\n");
674 nr5g_fapi_wls_print_stats();
678 pWls->nTotalFreeCnt++;
679 if (loc < MAX_DL_BUF_LOCATIONS)
680 pWls->nTotalDlBufFreeCnt[loc]++;
681 else if (loc < MAX_UL_BUF_LOCATIONS)
682 pWls->nTotalUlBufFreeCnt++;
684 if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
685 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
690 //------------------------------------------------------------------------------
691 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
693 * @param A pointer to a wls instance
695 * @return 0 if SUCCESS
697 * @description This function initializes the WLS layer FAPI2PHY interface
698 * primitives and allocates memory needed to exchange APIs
699 * between FAPI and PHY.
701 //------------------------------------------------------------------------------
702 uint8_t nr5g_fapi_wls_memory_init(
705 uint32_t nBlocks = 0;
706 p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
708 if (FAILURE == wls_fapi_create_partition(p_wls))
711 if ((nBlocks = wls_fapi_add_blocks_to_ul()) == 0) {
712 NR5G_FAPI_LOG(ERROR_LOG, ("Unable to allocate blocks to PHY"));