X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=fapi_5g%2Fsource%2Fframework%2Fwls%2Flib%2Fnr5g_fapi_wls.c;fp=fapi_5g%2Fsource%2Fframework%2Fwls%2Flib%2Fnr5g_fapi_wls.c;h=2ae97b067688d3b43993604e0ef7728170af4d6c;hp=0000000000000000000000000000000000000000;hb=9d66fca5c45c8b3e0d6eab6d51a90c8e9d2614dc;hpb=2fbf70096f64af622da983e88c5a64e90ad9bdbd diff --git a/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c b/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c new file mode 100644 index 0000000..2ae97b0 --- /dev/null +++ b/fapi_5g/source/framework/wls/lib/nr5g_fapi_wls.c @@ -0,0 +1,915 @@ +/****************************************************************************** +* +* Copyright (c) 2019 Intel. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*******************************************************************************/ + +/** + * @file This file has Shared Memory interface functions between FAPI and PHY + * @defgroup nr5g_fapi_source_framework_wls_lib_group + **/ + +#include "nr5g_fapi_framework.h" +#include "nr5g_fapi_internal.h" +#include "nr5g_fapi_wls.h" +#include "nr5g_fapi_config_loader.h" +#include "nr5g_fapi_log.h" +#include "nr5g_fapi_memory.h" + +nr5g_fapi_wls_context_t g_wls_ctx; + +static uint32_t g_to_free_send_list_cnt[TO_FREE_SIZE] = { 0 }; +static uint64_t g_to_free_send_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} }; +static uint32_t g_to_free_recv_list_cnt[TO_FREE_SIZE] = { 0 }; +static uint64_t g_to_free_recv_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} }; + +static uint8_t alloc_track[ALLOC_TRACK_SIZE]; + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param void + * + * @return A pointer to WLS Context stucture + * + * @description + * This function returns the WLS Context structure which has WLS related parameters + * +**/ +//------------------------------------------------------------------------------ +inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context( + ) +{ + return &g_wls_ctx; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] ptr Pointer to display + * @param[in] size Size of data + * + * @return void + * + * @description + * This function displays content of Buffer - Used for debugging + * +**/ +//------------------------------------------------------------------------------ +void nr5g_fapi_wls_show_data( + void *ptr, + uint32_t size) +{ + uint8_t *d = ptr; + int i; + + for (i = 0; i < size; i++) { + if (!(i & 0xf)) + printf("\n"); + printf("%02x ", d[i]); + } + printf("\n"); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param N/A + * + * @return N/A + * + * @description + * This function prints to the console FAPI stats + * +**/ +//------------------------------------------------------------------------------ +void nr5g_fapi_wls_print_stats( + void) +{ + p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context(); + printf(" nTotalBlocks[%5d] nAllocBlocks[%5d] nFreeBlocks[%5d]\n", + pWls->nTotalBlocks, pWls->nAllocBlocks, + (pWls->nTotalBlocks - pWls->nAllocBlocks)); + printf(" nTotalAllocCnt[%5d] nTotalFreeCnt[%5d] Diff[%5d]\n", + pWls->nTotalAllocCnt, pWls->nTotalFreeCnt, + (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt)); + uint32_t nFinalTotalDlBufAllocCnt = 0, nFinalTotalDlBufFreeCnt = 0, idx; + +//#define PRINTF_DEBUG(fmt, args...) //printf(fmt, ## args) +#define PRINTF_DEBUG(fmt, args...) + PRINTF_DEBUG("\n"); + PRINTF_DEBUG("\n nDlBufAllocCnt: \n"); + for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) { + nFinalTotalDlBufAllocCnt += pWls->nTotalDlBufAllocCnt[idx]; + PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufAllocCnt[idx]); + } + PRINTF_DEBUG("\n"); + PRINTF_DEBUG("\n nDlBufFreeCnt: \n"); + for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) { + nFinalTotalDlBufFreeCnt += pWls->nTotalDlBufFreeCnt[idx]; + PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufFreeCnt[idx]); + } + PRINTF_DEBUG("\n\n"); + + printf(" nDlBufAllocCnt[%5d] nDlBufFreeCnt[%5d] Diff[%5d]\n", + nFinalTotalDlBufAllocCnt, nFinalTotalDlBufFreeCnt, + (nFinalTotalDlBufAllocCnt - nFinalTotalDlBufFreeCnt)); + printf + (" nUlBufAllocCnt[%5d] nUlBufFreeCnt[%5d] Diff[%5d]\n\n", + pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt, + (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt)); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] ptr Address to convert + * + * @return Converted address + * + * @description + * This function converts Virtual Address to Physical Address + * +**/ +//------------------------------------------------------------------------------ +uint64_t nr5g_fapi_wls_va_to_pa( + WLS_HANDLE h_wls, + void *ptr) +{ + return ((uint64_t) WLS_VA2PA(h_wls, ptr)); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] ptr Address to convert + * + * @return Converted address + * + * @description + * This function converts Physical Address to Virtual Address + * +**/ +//------------------------------------------------------------------------------ +void *nr5g_fapi_wls_pa_to_va( + WLS_HANDLE h_wls, + uint64_t ptr) +{ + return ((void *)WLS_PA2VA(h_wls, ptr)); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param void + * + * @return Number of blocks added + * + * @description + * This function add WLS blocks to the L1 Array which will be used by L1 in + * every TTI to populate and send back APIs to the MAC + * +**/ +//------------------------------------------------------------------------------ +uint8_t wls_fapi_add_blocks_to_ul( + void) +{ + int num_blocks = 0; + p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context(); + WLS_HANDLE h_wls = pWls->h_wls[NR5G_FAPI2PHY_WLS_INST]; + + void *pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS); + if (!pMsg) { + return num_blocks; + } + + /* allocate blocks for UL transmittion */ + while (WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls, pMsg)) > 0) { + num_blocks++; + pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS); + if (!pMsg) + break; + } + + // free not enqueued block + if (pMsg) { + wls_fapi_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS); + } + + return num_blocks; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param A pointer to the phy instance table. + * + * @return 0 if SUCCESS + * + * @description This function initializes WLS layer primitives and allocates + * memory needed to exchange APIs between FAPI and PHY. +**/ +//------------------------------------------------------------------------------ +uint8_t nr5g_fapi_wls_init( + p_nr5g_fapi_cfg_t cfg) +{ + p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context(); + const char *dev_name = "wls"; + + if (p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST] && + p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]) { + // NR5G_FAPI_LOG(ERROR_LOG, ("WLS instance already opened!")); + return FAILURE; + } + + p_wls_ctx->shmem_size = cfg->wls.shmem_size; + p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] = + WLS_Open_Dual(dev_name /*"wls"cfg->wls.device_name */ , + WLS_SLAVE_CLIENT, + cfg->wls.shmem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]); + if ((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) && + (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST])) { + // NR5G_FAPI_LOG(ERROR_LOG,("[NR5G_FAPI_ WLS] WLS instance connected.")); + return FAILURE; + } + // Issue WLS_Alloc() for FAPI2MAC + p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST], + p_wls_ctx->shmem_size); + + if (NULL == p_wls_ctx->shmem) { + printf("Unable to alloc WLS Memory for FAPI2MAC\n"); + return FAILURE; + } + + p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST], + p_wls_ctx->shmem_size); + p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem; + p_wls_ctx->nTotalMemorySize = p_wls_ctx->shmem_size; + if (NULL == p_wls_ctx->shmem) { + printf("Unable to alloc WLS Memory\n"); + return FAILURE; + } + + pthread_mutex_init((pthread_mutex_t *) + &p_wls_ctx->fapi2phy_lock_send, NULL); + pthread_mutex_init((pthread_mutex_t *) + &p_wls_ctx->fapi2phy_lock_alloc, NULL); + pthread_mutex_init((pthread_mutex_t *) + &p_wls_ctx->fapi2mac_lock_send, NULL); + pthread_mutex_init((pthread_mutex_t *) + &p_wls_ctx->fapi2mac_lock_alloc, NULL); + return SUCCESS; +} + +//------------------------------------------------------------------------------------------- +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] pMemArray Pointer to WLS Memory Management Structure + * @param[in] pMemArrayMmeory pointer to flat buffer that was allocated + * @param[in] totalSize total size of flat buffer allocated + * @param[in] nBlockSize Size of each block that needs to be partitoned by the memory manager + * + * @return 0 if SUCCESS + * + * @description + * This function creates memory blocks from a flat buffer which will be used for communication between FAPI and PHY + * +**/ +//------------------------------------------------------------------------------------------- +uint32_t wls_fapi_create_mem_array( + PWLS_FAPI_MEM_STRUCT pMemArray, + void *pMemArrayMemory, + uint32_t totalSize, + uint32_t nBlockSize) +{ + + int numBlocks = totalSize / nBlockSize; + void **ptr; + uint32_t i; + + printf + ("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n", + pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks); + + // Can't be less than pointer size + if (nBlockSize < sizeof(void *)) { + return FAILURE; + } + // Can't be less than one block + if (totalSize < sizeof(void *)) { + return FAILURE; + } + + pMemArray->ppFreeBlock = (void **)pMemArrayMemory; + pMemArray->pStorage = pMemArrayMemory; + pMemArray->pEndOfStorage = + ((unsigned long *)pMemArrayMemory) + + numBlocks * nBlockSize / sizeof(unsigned long); + pMemArray->nBlockSize = nBlockSize; + pMemArray->nBlockCount = numBlocks; + + // Initialize single-linked list of free blocks; + ptr = (void **)pMemArrayMemory; + for (i = 0; i < pMemArray->nBlockCount; i++) { +#ifdef MEMORY_CORRUPTION_DETECT + // Fill with some pattern + uint8_t *p = (uint8_t *) ptr; + uint32_t j; + + p += (nBlockSize - 16); + for (j = 0; j < 16; j++) { + p[j] = MEMORY_CORRUPTION_DETECT_FLAG; + } +#endif + + if (i == pMemArray->nBlockCount - 1) { + *ptr = NULL; // End of list + } else { + // Points to the next block + *ptr = (void **)(((uint8_t *) ptr) + nBlockSize); + ptr += nBlockSize / sizeof(unsigned long); + } + } + + NR5G_FAPI_MEMSET(alloc_track, sizeof(uint8_t) * ALLOC_TRACK_SIZE, 0, + sizeof(uint8_t) * ALLOC_TRACK_SIZE); + + return SUCCESS; +} + +//------------------------------------------------------------------------------------------- +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] pWls Pointer to the nr5g_fapi_wls_ctx structure + * + * @return 0 if SUCCESS + * + * @description + * This function created a partition and blocks of WLS memory for API exchange between FAPI and PHY + * +**/ +//------------------------------------------------------------------------------------------- +int wls_fapi_create_partition( + p_nr5g_fapi_wls_context_t pWls) +{ +#define WLS_HUGE_DEF_PAGE_SIZEA 0x40000000LL + static long hugePageSize = WLS_HUGE_DEF_PAGE_SIZEA; + // NR5G_FAPI_MEMSET(pWls->pWlsMemBase , 0xCC, pWls->nTotalMemorySize); // This is done by the Master Only + pWls->pPartitionMemBase = + (void *)(((uint8_t *) pWls->pWlsMemBase) + hugePageSize); + pWls->nPartitionMemSize = (pWls->nTotalMemorySize - hugePageSize); + + pWls->nTotalBlocks = pWls->nPartitionMemSize / MSG_MAXSIZE; + return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, + pWls->nPartitionMemSize, MSG_MAXSIZE); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2) + * @param[out] ppBlock Pointer where the allocated memory block is stored + * + * @return 0 if SUCCESS + * + * @description This function allocates a memory block from the pool + * +**/ +//------------------------------------------------------------------------------ +uint32_t wls_fapi_alloc_mem_array( + PWLS_FAPI_MEM_STRUCT pMemArray, + void **ppBlock) +{ + int idx; + + if (pMemArray->ppFreeBlock == NULL) { + printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n"); + return FAILURE; + } + // FIXME: Remove after debugging + if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) || + ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) { + printf + ("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n", + pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock); + return FAILURE; + } + + pMemArray->ppFreeBlock = + (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + *pMemArray->ppFreeBlock = + (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + + if ((*pMemArray->ppFreeBlock != NULL) && + (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) || + ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) { + fprintf(stderr, + "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + return FAILURE; + } + + *ppBlock = (void *)pMemArray->ppFreeBlock; + pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock); + + idx = + (((uint64_t) * ppBlock - + (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize; + if (alloc_track[idx]) { + printf + ("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, + *pMemArray->ppFreeBlock); + return FAILURE; + } else { +#ifdef MEMORY_CORRUPTION_DETECT + uint32_t nBlockSize = pMemArray->nBlockSize, i; + uint8_t *p = (uint8_t *) * ppBlock; + + p += (nBlockSize - 16); + for (i = 0; i < 16; i++) { + p[i] = MEMORY_CORRUPTION_DETECT_FLAG; + } +#endif + alloc_track[idx] = 1; + } + + //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock); + + return SUCCESS; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] A pointer to the FAPI Memory Structure (Initialized by L2) + * @param[in] pBlock Pointer where the allocated memory block is stored + * + * @return 0 if SUCCESS + * + * @description This function frees a WLS block of memory and adds + * it back to the pool + * +**/ +//------------------------------------------------------------------------------ +uint32_t wls_fapi_free_mem_array( + PWLS_FAPI_MEM_STRUCT pMemArray, + void *pBlock) +{ + int idx; + unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1); + + pBlock = (void *)((unsigned long)pBlock & ~mask); + + if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) { + printf + ("wls_fapi_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n", + pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage); + return FAILURE; + } + + idx = + (int)(((uint64_t) pBlock - + (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize; + + if (alloc_track[idx] == 0) { + printf + ("wls_fapi_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n", + pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, pBlock); + return SUCCESS; + } else { +#ifdef MEMORY_CORRUPTION_DETECT + uint32_t nBlockSize = pMemArray->nBlockSize, i; + uint8_t *p = (uint8_t *) pBlock; + + p += (nBlockSize - 16); + for (i = 0; i < 16; i++) { + if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG) { + printf("ERROR: Corruption\n"); + nr5g_fapi_wls_print_stats(); + exit(-1); + } + } +#endif + alloc_track[idx] = 0; + } + + if (((void *)pMemArray->ppFreeBlock) == pBlock) { + // Simple protection against freeing of already freed block + return SUCCESS; + } + // FIXME: Remove after debugging + if ((pMemArray->ppFreeBlock != NULL) + && (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) + || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))) { + printf + ("wls_fapi_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n", + pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock); + return FAILURE; + } + // FIXME: Remove after debugging + if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) { + printf("wls_fapi_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n", + pMemArray, pBlock); + return FAILURE; + } + + *((void **)pBlock) = + (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0); + pMemArray->ppFreeBlock = + (void **)((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0); + + //printf("Block freed [%p,%p]\n", pMemArray, pBlock); + + return SUCCESS; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param size (if 0 fixed size from pool) + * @param Number of locations + * + * @return 0 if SUCCESS + * + * @description This function initializes WLS layer primitives and allocates + * memory needed to exchange APIs between FAPI and PHY. +**/ +//------------------------------------------------------------------------------ +void *wls_fapi_alloc_buffer( + uint32_t size, + uint32_t loc) +{ + void *pBlock = NULL; + p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context(); + + if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) { + NR5G_FAPI_LOG(ERROR_LOG, ("unable to get lock alloc pthread mutex")); + exit(-1); + } + + if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS) { + printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size, + loc); + nr5g_fapi_wls_print_stats(); + exit(-1); + } else { + pWls->nAllocBlocks++; + } + + //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks); + + //printf("[%p]\n", pBlock); + + pWls->nTotalAllocCnt++; + if (loc < MAX_DL_BUF_LOCATIONS) + pWls->nTotalDlBufAllocCnt[loc]++; + else if (loc < MAX_UL_BUF_LOCATIONS) + pWls->nTotalUlBufAllocCnt++; + + if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) { + NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex")); + exit(-1); + } + + return pBlock; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] *pMsg Pointer to free + * + * @return void + * + * @descriptioni This function frees a block of memory and adds it back to + * the pool. + * +**/ +//------------------------------------------------------------------------------ +void wls_fapi_free_buffer( + void *pMsg, + uint32_t loc) +{ + p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context(); + + if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) { + NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex")); + exit(-1); + } + //printf("----------------wls_fapi_free_buffer: buf[%p] loc[%d]\n", pMsg, loc); + if (wls_fapi_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS) { + pWls->nAllocBlocks--; + } else { + printf("wls_fapi_free_buffer Free error\n"); + nr5g_fapi_wls_print_stats(); + exit(-1); + } + + pWls->nTotalFreeCnt++; + if (loc < MAX_DL_BUF_LOCATIONS) + pWls->nTotalDlBufFreeCnt[loc]++; + else if (loc < MAX_UL_BUF_LOCATIONS) + pWls->nTotalUlBufFreeCnt++; + + if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) { + NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex")); + exit(-1); + } +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param A pointer to a wls instance + * + * @return 0 if SUCCESS + * + * @description This function initializes the WLS layer FAPI2PHY interface + * primitives and allocates memory needed to exchange APIs + * between FAPI and PHY. +**/ +//------------------------------------------------------------------------------ +uint8_t nr5g_fapi2Phy_wls_init( + p_nr5g_fapi_wls_context_t pwls) +{ + int nBlocks = 0; + uint8_t retval = SUCCESS; + + retval = wls_fapi_create_partition(pwls); + if ((nBlocks = wls_fapi_add_blocks_to_ul()) == 0) { + return FAILURE; + } + + return retval; +} + +uint8_t get_stats_location( + uint8_t msg_type) +{ + uint8_t loc; + switch (msg_type) { + case MSG_TYPE_PHY_CONFIG_REQ: + loc = MEM_STAT_CONFIG_REQ; + break; + case MSG_TYPE_PHY_START_REQ: + loc = MEM_STAT_START_REQ; + break; + case MSG_TYPE_PHY_STOP_REQ: + loc = MEM_STAT_STOP_REQ; + break; + case MSG_TYPE_PHY_SHUTDOWN_REQ: + loc = MEM_STAT_SHUTDOWN_REQ; + break; + case MSG_TYPE_PHY_DL_CONFIG_REQ: + loc = MEM_STAT_DL_CONFIG_REQ; + break; + case MSG_TYPE_PHY_UL_CONFIG_REQ: + loc = MEM_STAT_UL_CONFIG_REQ; + break; + case MSG_TYPE_PHY_UL_DCI_REQ: + loc = MEM_STAT_UL_DCI_REQ; + break; + case MSG_TYPE_PHY_TX_REQ: + loc = MEM_STAT_TX_REQ; + break; + case MSG_TYPE_PHY_DL_IQ_SAMPLES: + loc = MEM_STAT_DL_IQ_SAMPLES; + break; + case MSG_TYPE_PHY_UL_IQ_SAMPLES: + loc = MEM_STAT_UL_IQ_SAMPLES; + break; + default: + loc = MEM_STAT_DEFAULT; + } + + return loc; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] pListElem Pointer to List element header + * @param[in] idx Subframe Number + * + * @return Number of blocks freed + * + * @description This function Frees all the blocks in a List Element Linked + * List coming from L1 by storing them into an array to be + * freed at a later point in time. +**/ +//------------------------------------------------------------------------------ +void wls_fapi_add_recv_apis_to_free( + PMAC2PHY_QUEUE_EL pListElem, + uint32_t idx) +{ + PMAC2PHY_QUEUE_EL pNextMsg = NULL; + L1L2MessageHdr *p_msg_header = NULL; + PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL; + int count, i; + uint8_t *ptr = NULL; + + WLS_HANDLE h_wls; + p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context(); + h_wls = p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]; + + count = g_to_free_recv_list_cnt[idx]; + pNextMsg = pListElem; + while (pNextMsg) { + if (count >= TOTAL_FREE_BLOCKS) { + NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n" + "\t\t\t\tlist index: %d list count: %d max list count: %d", + __func__, idx, count, TOTAL_FREE_BLOCKS)); + return; + } + + g_to_free_recv_list[idx][count++] = (uint64_t) pNextMsg; + p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1); + if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) { + p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header; + for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) { + ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload; + ptr = (uint8_t *) nr5g_fapi_wls_pa_to_va(h_wls, (uint64_t) ptr); + + if (ptr) { + g_to_free_recv_list[idx][count++] = (uint64_t) ptr; + } + } + } + pNextMsg = pNextMsg->pNext; + } + + g_to_free_recv_list[idx][count] = 0L; + g_to_free_recv_list_cnt[idx] = count; + + NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count)); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] idx subframe Number + * + * @return Number of blocks freed + * + * @description This function frees all blocks that have been added to the + * free array +**/ +//------------------------------------------------------------------------------ +void wls_fapi_free_recv_free_list( + uint32_t idx) +{ + PMAC2PHY_QUEUE_EL pNextMsg = NULL; + int count = 0; + + if (idx >= TO_FREE_SIZE) { + NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx)); + return; + } + + pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count]; + while (pNextMsg) { + wls_fapi_free_buffer(pNextMsg, MIN_UL_BUF_LOCATIONS); + g_to_free_recv_list[idx][count++] = 0L; + if (g_to_free_recv_list[idx][count]) + pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count]; + else + pNextMsg = 0L; + } + + NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count)); + g_to_free_recv_list_cnt[idx] = 0; + + return; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] pListElem Pointer to List element header + * @param[in] idx Subframe Number + * + * @return Number of blocks freed + * + * @description This function Frees all the blocks in a List Element Linked + * List coming from L1 by storing them into an array to be + * freed at a later point in time. +**/ +//------------------------------------------------------------------------------ +void wls_fapi_add_send_apis_to_free( + PMAC2PHY_QUEUE_EL pListElem, + uint32_t idx) +{ + PMAC2PHY_QUEUE_EL pNextMsg = NULL; + L1L2MessageHdr *p_msg_header = NULL; + PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL; + int count, i; + uint8_t *ptr = NULL; + + count = g_to_free_send_list_cnt[idx]; + pNextMsg = pListElem; + while (pNextMsg) { + if (count >= TOTAL_FREE_BLOCKS) { + NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n" + "\t\t\t\tlist index: %d list count: %d max list count: %d", + __func__, idx, count, TOTAL_FREE_BLOCKS)); + return; + } + + g_to_free_send_list[idx][count++] = (uint64_t) pNextMsg; + p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1); + if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) { + p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header; + for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) { + ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload; + if (ptr) { + g_to_free_send_list[idx][count++] = (uint64_t) ptr; + } + } + } + pNextMsg = pNextMsg->pNext; + } + + g_to_free_send_list[idx][count] = 0L; + g_to_free_send_list_cnt[idx] = count; + + NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count)); +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] idx subframe Number + * + * @return Number of blocks freed + * + * @description This function frees all blocks that have been added to the + * free array +**/ +//------------------------------------------------------------------------------ +void wls_fapi_free_send_free_list( + uint32_t idx) +{ + PMAC2PHY_QUEUE_EL pNextMsg = NULL; + L1L2MessageHdr *p_msg_header = NULL; + int count = 0, loc = 0; + + if (idx >= TO_FREE_SIZE) { + NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx)); + return; + } + + pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count]; + while (pNextMsg) { + p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1); + loc = get_stats_location(p_msg_header->nMessageType); + wls_fapi_free_buffer(pNextMsg, loc); + g_to_free_send_list[idx][count++] = 0L; + if (g_to_free_send_list[idx][count]) + pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count]; + else + pNextMsg = 0L; + } + + NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count)); + g_to_free_send_list_cnt[idx] = 0; + + return; +} + +//------------------------------------------------------------------------------ +/** @ingroup nr5g_fapi_source_framework_wls_lib_group + * + * @param[in] idx subframe Number + * + * @return Number of blocks freed + * + * @description This function frees all blocks that have been added to the + * free array +**/ +//------------------------------------------------------------------------------ +void wls_fapi_free_list_all( + void) +{ + uint32_t idx; + + for (idx = 0; idx < TO_FREE_SIZE; idx++) { + wls_fapi_free_send_free_list(idx); + wls_fapi_free_recv_free_list(idx); + } + + nr5g_fapi_wls_print_stats(); +}