X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?p=o-du%2Fphy.git;a=blobdiff_plain;f=wls_lib%2Fwls_lib.c;fp=wls_lib%2Fwls_lib.c;h=83c82ffb55a95ab8e3d6a8b226c428262a299dd9;hp=0000000000000000000000000000000000000000;hb=9d66fca5c45c8b3e0d6eab6d51a90c8e9d2614dc;hpb=2fbf70096f64af622da983e88c5a64e90ad9bdbd diff --git a/wls_lib/wls_lib.c b/wls_lib/wls_lib.c new file mode 100644 index 0000000..83c82ff --- /dev/null +++ b/wls_lib/wls_lib.c @@ -0,0 +1,836 @@ +/****************************************************************************** +* +* 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. +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ttypes.h" +#include "wls_lib.h" +#include "wls.h" +#include "syslib.h" + +#define WLS_MAP_SHM 1 + +#define WLS_PHY_SHM_FILE_NAME "/tmp/phyappshm" + +#define HUGE_PAGE_FILE_NAME "/mnt/huge/page" + +#define DIV_ROUND_OFFSET(X,Y) ( X/Y + ((X%Y)?1:0) ) + +#define WLS_LIB_USER_SPACE_CTX_SIZE DMA_MAP_MAX_BLOCK_SIZE + +#define PLIB_ERR(x, args...) printf("wls_lib: "x, ## args); +#define PLIB_INFO(x, args...) printf("wls_lib: "x, ## args); + +#ifdef _DEBUG_ +#define PLIB_DEBUG(x, args...) printf("wls_lib debug: "x, ## args); +#else +#define PLIB_DEBUG(x, args...) do { } while(0) +#endif + +#ifdef __x86_64__ +#define WLS_LIB_MMAP mmap +#else +#define WLS_LIB_MMAP mmap64 +#endif + +extern int gethugepagesizes(long pagesizes[], int n_elem); +extern int hugetlbfs_unlinked_fd(void); + + +static pthread_mutex_t wls_put_lock; +static pthread_mutex_t wls_get_lock; + +static int wls_dev_fd = 0; +static wls_us_ctx_t* wls_us_ctx = NULL; + +static uint64_t wls_kernel_va_to_user_va(void *pWls_us, uint64_t ptr); + +int ipc_file = 0; + +static int wls_VirtToPhys(void* virtAddr, uint64_t* physAddr) +{ + int mapFd; + uint64_t page; + unsigned int pageSize; + unsigned long virtualPageNumber; + + mapFd = open ("/proc/self/pagemap" , O_RDONLY ); + if (mapFd < 0 ) + { + PLIB_ERR("Could't open pagemap file\n"); + return -1; + } + + /*get standard page size*/ + pageSize = getpagesize(); + + virtualPageNumber = (unsigned long) virtAddr / pageSize ; + + lseek(mapFd , virtualPageNumber * sizeof(uint64_t) , SEEK_SET ); + + if(read(mapFd ,&page , sizeof(uint64_t)) < 0 ) + { + close(mapFd); + PLIB_ERR("Could't read pagemap file\n"); + return -1; + } + + *physAddr = (( page & 0x007fffffffffffffULL ) * pageSize ); + + close(mapFd); + + return 0; +} + +static void wls_mutex_destroy(pthread_mutex_t* pMutex) +{ + pthread_mutex_destroy(pMutex); +} + +static void wls_mutex_init(pthread_mutex_t* pMutex) +{ + pthread_mutexattr_t prior; + pthread_mutexattr_init(&prior); + pthread_mutexattr_setprotocol(&prior, PTHREAD_PRIO_INHERIT); + pthread_mutex_init(pMutex, &prior); + pthread_mutexattr_destroy(&prior); +} + +static void wls_mutex_lock(pthread_mutex_t* pMutex) +{ + pthread_mutex_lock(pMutex); +} + +static void wls_mutex_unlock(pthread_mutex_t* pMutex) +{ + pthread_mutex_unlock(pMutex); +} + +static uint64_t wls_kernel_va_to_user_va(void *pWls_us, uint64_t ptr) +{ + unsigned long ret = 0; + wls_us_ctx_t* pUs = (wls_us_ctx_t*)pWls_us; + + uint64_t kva = (uint64_t) pUs->wls_us_kernel_va; + uint64_t uva = (uint64_t) pUs->wls_us_user_space_va; + + ret = (uva + (ptr - kva)); + + PLIB_DEBUG("kva %lx to uva %lx [offset %d]\n",kva, ret, (kva - ret)); + return ret; +} + +static uint64_t wls_kernel_va_to_user_va_dest(void *pWls_us, uint64_t ptr) +{ + unsigned long ret = 0; + wls_us_ctx_t* pUs = (wls_us_ctx_t*)pWls_us; + + uint64_t kva = (uint64_t) pUs->dst_kernel_va; + uint64_t uva = (uint64_t) pUs->dst_user_va; + + ret = (uva + (ptr - kva)); + + PLIB_DEBUG("kva %lx to uva %lx [offset %d]\n",kva, ret, (kva - ret)); + return ret; +} + + +void* WLS_Open(const char *ifacename, unsigned int mode, unsigned long long nWlsMemorySize) +{ + wls_us_ctx_t* pWls_us = NULL; + unsigned int ret = 0; + wls_open_req_t params; + int i, len; + char temp[WLS_DEV_SHM_NAME_LEN]; + +#ifdef __x86_64__ + params.ctx = 64L; +#else + params.ctx = 32L; +#endif + + params.ctx_pa = 0; + params.size = WLS_LIB_USER_SPACE_CTX_SIZE; + + if(sizeof(wls_us_ctx_t) >= 64*1024){ + PLIB_ERR("WLS_Open %ld \n", sizeof(wls_us_ctx_t)); + return NULL; + } + + if (!wls_us_ctx) { + PLIB_INFO("Open %s 0x%08lx\n", ifacename, WLS_IOC_OPEN); + + if ((wls_dev_fd = open(ifacename, O_RDWR | O_SYNC)) < 0){ + PLIB_ERR("Open filed [%d]\n", wls_dev_fd); + return NULL; + } + /* allocate block in shared space */ + if((ret = ioctl(wls_dev_fd, WLS_IOC_OPEN, ¶ms)) < 0) { + PLIB_ERR("Open filed [%d]\n", ret); + return NULL; + } + + PLIB_DEBUG("params: kernel va 0x%016llx pa 0x%016llx size %ld\n", + params.ctx, params.ctx_pa, params.size); + + if (params.ctx_pa) { + /* remap to user space the same block */ + pWls_us = (wls_us_ctx_t*) WLS_LIB_MMAP(NULL, + params.size, + PROT_READ|PROT_WRITE , + MAP_SHARED, + wls_dev_fd, + params.ctx_pa); + + if( pWls_us == MAP_FAILED ){ + PLIB_ERR("mmap has failed (%d:%s) 0x%016lx [size %d]\n", errno, strerror(errno),params.ctx_pa, params.size); + return NULL; + } + + PLIB_DEBUG("Local: pWls_us 0x%016p\n", pWls_us); + + PLIB_DEBUG("size wls_us_ctx_t %d\n", sizeof(wls_us_ctx_t)); + PLIB_DEBUG(" ul free : off 0x%016lx\n",((unsigned long) &pWls_us->ul_free_block_pq -(unsigned long)pWls_us)); + PLIB_DEBUG(" get_queue: off 0x%016lx\n",((unsigned long) &pWls_us->get_queue -(unsigned long)pWls_us)); + PLIB_DEBUG(" put_queue: off 0x%016lx\n",((unsigned long) &pWls_us->put_queue -(unsigned long)pWls_us)); + + //memset(pWls_us, 0, params.size); + + pWls_us->padding_wls_us_user_space_va = 0LL; + + pWls_us->wls_us_user_space_va = pWls_us; + + pWls_us->wls_us_kernel_va = (uint64_t) params.ctx; + pWls_us->wls_us_pa = (uint64_t) params.ctx_pa; + pWls_us->wls_us_ctx_size = params.size; + + PLIB_INFO("User Space Lib Context: us va 0x%016lx kernel va 0x%016lx pa 0x%016lx size %d \n", + (uintptr_t)pWls_us->wls_us_user_space_va, + pWls_us->wls_us_kernel_va, + pWls_us->wls_us_pa, + pWls_us->wls_us_ctx_size); + + wls_mutex_init(&wls_put_lock); + wls_mutex_init(&wls_get_lock); + + pWls_us->mode = mode; + PLIB_INFO("\nMode %d\n", pWls_us->mode); + + PLIB_INFO("\nWLS device %s [%d]\n", ifacename, (int)strlen(ifacename)); + strncpy(temp, ifacename, WLS_DEV_SHM_NAME_LEN - 1); + len = strlen(ifacename); + if (len < WLS_DEV_SHM_NAME_LEN - 1) + strncpy(pWls_us->wls_dev_name, temp, len); + else + strncpy(pWls_us->wls_dev_name, temp, WLS_DEV_SHM_NAME_LEN - 1); + for(i = 0; i < MIN(strlen(pWls_us->wls_dev_name),WLS_DEV_SHM_NAME_LEN); i++) + if(pWls_us->wls_dev_name[i] != '/') + pWls_us->wls_shm_name[i] = pWls_us->wls_dev_name[i]; + else + pWls_us->wls_shm_name[i] = '_'; + + wls_us_ctx = pWls_us; + } + else { + PLIB_ERR("Open filed: incorrect allocation \n"); + return NULL; + } + } + + return wls_us_ctx; +} + +int WLS_Ready(void* h) +{ + int ret = 0; + wls_event_req_t params; + + if (!wls_us_ctx || !wls_dev_fd){ + PLIB_ERR("Library was not opened\n"); + return -1; + } + + params.event_to_wls = WLS_EVENT_IA_READY; + params.event_param = 0; + + /* free block in shared space */ + if((ret = ioctl(wls_dev_fd, WLS_IOC_EVENT, ¶ms)) < 0) { + PLIB_ERR("Event filed [%d]\n", ret); + return ret; + } + + return 0; +} + +int WLS_Close(void* h) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t*)h; + wls_close_req_t params; + int ret = 0; + + if (!wls_us_ctx || !wls_dev_fd){ + PLIB_ERR("Library was not opened\n"); + return -1; + } + + if ((unsigned long)pWls_us != (unsigned long )wls_us_ctx){ + PLIB_ERR("Incorret handle %lx [expected %lx]\n", (unsigned long)pWls_us, (unsigned long )wls_us_ctx); + return -1; + } + + params.ctx = pWls_us->wls_us_kernel_va; + params.ctx_pa = pWls_us->wls_us_pa; + params.size = pWls_us->wls_us_ctx_size; + + /* free block in shared space */ + if((ret = ioctl(wls_dev_fd, WLS_IOC_CLOSE, ¶ms)) < 0) { + PLIB_ERR("Close filed [%d]\n", ret); + return 0; + } + + /* unmap to user space */ + munmap(pWls_us, pWls_us->wls_us_ctx_size); + + wls_mutex_destroy(&wls_put_lock); + wls_mutex_destroy(&wls_get_lock); + + close(wls_dev_fd); + + wls_us_ctx = NULL; + wls_dev_fd = 0; + + return 0; +} + + +void* WLS_Alloc(void* h, unsigned int size) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + long pageSize[1]; + long hugePageSize; + long nHugePage; + + hugepage_tabl_t* pHugePageTlb = &pWls_us->hugepageTbl[0]; + + void* pvirtAddr = NULL; + int count; + int fd; + + char shm_file_name[256]; + + fd = hugetlbfs_unlinked_fd(); + + if (fd < 0) + PLIB_ERR("Unable to open temp file in hugetlbfs (%s)", strerror(errno)); + + gethugepagesizes(pageSize,1); + hugePageSize = pageSize[0]; + + PLIB_INFO("hugePageSize on the system is %ld\n", hugePageSize); + + /* calculate total number of hugepages */ + nHugePage = DIV_ROUND_OFFSET(size, hugePageSize); + + if (nHugePage >= MAX_N_HUGE_PAGES){ + PLIB_INFO("not enough hugepages: need %ld system has %d\n", nHugePage, MAX_N_HUGE_PAGES); + return NULL; + } + + if(pHugePageTlb == NULL ) + { + PLIB_INFO("Table memory allocation failed\n"); + return NULL; + } + +#if WLS_MAP_SHM +{ + snprintf(shm_file_name, WLS_DEV_SHM_NAME_LEN, "%s_%s", WLS_PHY_SHM_FILE_NAME, pWls_us->wls_shm_name); + PLIB_INFO("shm open %s\n", shm_file_name); + ipc_file = open(shm_file_name, O_CREAT); // | O_EXCL maybe sometimes in future.. ;-) + if(ipc_file == -1){ + PLIB_ERR("open failed (%s)\n", strerror(errno) ); + return NULL; + } + + key_t key = ftok(shm_file_name, '4'); + int shm_handle = shmget(key, size, SHM_HUGETLB|SHM_R|SHM_W); + if(shm_handle == -1){ + PLIB_INFO("Create shared memory\n"); + shm_handle = shmget(key, size, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W); + } + else + PLIB_INFO("Attach to shared memory\n"); + + if(shm_handle == -1){ + PLIB_ERR("shmget has failed (%s) [size %ld]\n", strerror(errno), nHugePage * hugePageSize); + return NULL; + } + + pvirtAddr = shmat(shm_handle, 0, /*SHM_RND*/0); +} +#else + /* Allocate required number of pages */ + pvirtAddr = mmap(0,(nHugePage * hugePageSize), (PROT_READ|PROT_WRITE), MAP_SHARED, fd,0); +#endif + if(pvirtAddr == MAP_FAILED ) + { + PLIB_ERR("mmap has failed (%s) [size %ld]\n", strerror(errno), nHugePage * hugePageSize); + return NULL; + } + + PLIB_INFO("pvirtAddr 0x%016lx\n", (unsigned long)pvirtAddr); + + for(count = 0 ; count < nHugePage ; count++ ) + { + /*Incremented virtual address to next hugepage to create table*/ + pHugePageTlb[count].pageVa = ((unsigned char*)pvirtAddr + \ + ( count * hugePageSize )); + /*Creating dummy page fault in process for each page + inorder to get pagemap*/ + *(unsigned char*)pHugePageTlb[count].pageVa = 1; + + if(wls_VirtToPhys((uint64_t*) pHugePageTlb[count].pageVa, + &pHugePageTlb[count].pagePa ) == -1) + { + munmap(pvirtAddr, (nHugePage * hugePageSize)); + PLIB_ERR("Virtual to physical conversion failed\n"); + return NULL; + } + + //PLIB_INFO("id %d va 0x%016p pa 0x%016llx [%ld]\n", count, (uintptr_t)pHugePageTlb[count].pageVa, (uint64_t) pHugePageTlb[count].pagePa, hugePageSize); + } + + PLIB_INFO("WLS_Alloc: 0x%016lx [%d]\n", (unsigned long)pvirtAddr, size); + + close(fd); + + pWls_us->HugePageSize = (uint32_t)hugePageSize; + pWls_us->alloc_buffer = pvirtAddr; + pWls_us->alloc_size = (uint32_t)(nHugePage * hugePageSize); + + if (pWls_us->mode == WLS_MASTER_CLIENT){ + wls_us_ctx_t* pWls_usRem = NULL; + PLIB_INFO("Connecting to remote peer ...\n"); + while (pWls_us->dst_pa == 0) // wait for slave + ; + + /* remap to user space the same block */ + pWls_usRem = (wls_us_ctx_t*) WLS_LIB_MMAP(NULL, + sizeof(wls_us_ctx_t), + PROT_READ|PROT_WRITE , + MAP_SHARED, + wls_dev_fd, + pWls_us->dst_pa); + + if( pWls_us == MAP_FAILED ){ + PLIB_ERR("mmap has failed (%d:%s) 0x%016lx \n", errno, strerror(errno),pWls_us->dst_pa); + return NULL; + } + + PLIB_INFO("Remote: pWls_us 0x%p\n", pWls_usRem); + + PLIB_INFO("size wls_us_ctx_t %ld\n", sizeof(wls_us_ctx_t)); + PLIB_INFO(" ul free : off 0x%016lx\n",((unsigned long) &pWls_usRem->ul_free_block_pq -(unsigned long)pWls_usRem)); + PLIB_INFO(" get_queue: off 0x%016lx\n",((unsigned long) &pWls_usRem->get_queue -(unsigned long)pWls_usRem)); + PLIB_INFO(" put_queue: off 0x%016lx\n",((unsigned long) &pWls_usRem->put_queue -(unsigned long)pWls_usRem)); + + pWls_us->dst_user_va = (uint64_t) pWls_usRem ; + } + + + return pvirtAddr; +} + +int WLS_Free(void* h, PVOID pMsg) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + if ((unsigned long)pMsg != (unsigned long)pWls_us->alloc_buffer) { + PLIB_ERR("incorrect pMsg %lx [expected %lx]\n", (unsigned long)pMsg ,(unsigned long)pWls_us->alloc_buffer); + return -1; + } + + if (pWls_us->mode == WLS_MASTER_CLIENT){ + if(pWls_us->dst_user_va){ + munmap((void*)pWls_us->dst_user_va, sizeof(wls_us_ctx_t)); + pWls_us->dst_user_va = 0; + } + } + + PLIB_DEBUG("WLS_Free 0x%016lx", (unsigned long)pMsg); +#if WLS_MAP_SHM + shmdt(pMsg); + close (ipc_file); +#else + munmap(pMsg, pWls_us->alloc_size); +#endif + + + + return 0; +} + +int WLS_Put(void* h, unsigned long long pMsg, unsigned int MsgSize, unsigned short MsgTypeID, unsigned short Flags) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + int ret = 0; + + if ((unsigned long)h != (unsigned long)wls_us_ctx) { + PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx); + return -1; + } + + if(!WLS_IS_ONE_HUGE_PAGE(pMsg, MsgSize, WLS_HUGE_DEF_PAGE_SIZE)) { + PLIB_ERR("WLS_Put input error: buffer is crossing 2MB page boundary 0x%016llx size %ld\n", pMsg, (unsigned long)MsgSize); + } + + wls_mutex_lock(&wls_put_lock); + + if ((WLS_FLAGS_MASK & Flags)){ // multi block transaction + if (Flags & WLS_TF_SYN){ + PLIB_DEBUG("WLS_SG_FIRST\n"); + if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags, wls_kernel_va_to_user_va, (void*)pWls_us)) + { + PLIB_DEBUG("WLS_Get %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID); + } + } else if ((Flags & WLS_TF_SCATTER_GATHER) && !(Flags & WLS_TF_SYN) && !(Flags & WLS_TF_FIN)){ + PLIB_DEBUG("WLS_SG_NEXT\n"); + if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags, wls_kernel_va_to_user_va, (void*)pWls_us)) + { + PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID); + } + } else if (Flags & WLS_TF_FIN) { + wls_put_req_t params; + PLIB_DEBUG("WLS_SG_LAST\n"); + params.wls_us_kernel_va = pWls_us->wls_us_kernel_va; + if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags, wls_kernel_va_to_user_va, (void*)pWls_us)) + { + PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID); + } + + PLIB_DEBUG("List: call WLS_IOC_PUT\n"); + if((ret = ioctl(wls_dev_fd, WLS_IOC_PUT, ¶ms)) < 0) { + PLIB_ERR("Put filed [%d]\n", ret); + wls_mutex_unlock(&wls_put_lock); + return -1; + } + } else + PLIB_ERR("unsaported flags %x\n", WLS_FLAGS_MASK & Flags); + } else { // one block transaction + wls_put_req_t params; + params.wls_us_kernel_va = pWls_us->wls_us_kernel_va; + if (WLS_MsgEnqueue(&pWls_us->put_queue, pMsg, MsgSize, MsgTypeID, Flags, wls_kernel_va_to_user_va, (void*)pWls_us)) + { + PLIB_DEBUG("WLS_Put %lx %d type %d\n",(U64) pMsg, MsgSize, MsgTypeID); + } + + PLIB_DEBUG("One block: call WLS_IOC_PUT\n"); + if((ret = ioctl(wls_dev_fd, WLS_IOC_PUT, ¶ms)) < 0) { + PLIB_ERR("Put filed [%d]\n", ret); + wls_mutex_unlock(&wls_put_lock); + return -1; + } + } + wls_mutex_unlock(&wls_put_lock); + + return 0; +} + +int WLS_Check(void* h) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + if ((unsigned long)h != (unsigned long)wls_us_ctx) { + PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx); + return 0; + } + + PLIB_DEBUG("offset get_queue %lx\n",(U64)&pWls_us->get_queue - (U64)pWls_us); + + return WLS_GetNumItemsInTheQueue(&pWls_us->get_queue); +} + + +unsigned long long WLS_Get(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + WLS_MSG_HANDLE hMsg; + uint64_t pMsg = NULL; + + if ((unsigned long)h != (unsigned long)wls_us_ctx) { + PLIB_ERR("Incorrect user space context %lx [%lx]\n", (unsigned long)h, (unsigned long)wls_us_ctx); + return 0; + } + + PLIB_DEBUG("offset get_queue %lx\n",(U64)&pWls_us->get_queue - (U64)pWls_us); + wls_mutex_lock(&wls_get_lock); + + if (WLS_MsgDequeue(&pWls_us->get_queue, &hMsg, wls_kernel_va_to_user_va, (void*)pWls_us)) + { + PLIB_DEBUG("WLS_Get %lx %d type %d\n",(U64) hMsg.pIaPaMsg, hMsg.MsgSize, hMsg.TypeID); + pMsg = hMsg.pIaPaMsg; + *MsgSize = hMsg.MsgSize; + *MsgTypeID = hMsg.TypeID; + *Flags = hMsg.flags; + } + + wls_mutex_unlock(&wls_get_lock); + + return pMsg; +} + +int WLS_WakeUp(void* h) +{ + int ret; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + wls_wake_up_req_t params; + + if (!wls_us_ctx || !wls_dev_fd){ + PLIB_ERR("Library was not opened\n"); + return -1; + } + + params.ctx = (uint64_t)pWls_us; + params.wls_us_kernel_va = (uint64_t)pWls_us->wls_us_kernel_va; + + PLIB_DEBUG("WLS_WakeUp\n"); + + if((ret = ioctl(wls_dev_fd, WLS_IOC_WAKE_UP, ¶ms)) < 0) { + PLIB_ERR("Wake Up filed [%d]\n", ret); + return ret; + } + + return 0; +} + +int WLS_Wait(void* h) +{ + int ret; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + wls_wait_req_t params; + + if (!wls_us_ctx || !wls_dev_fd){ + PLIB_ERR("Library was not opened\n"); + return -1; + } + + params.ctx = (uint64_t)pWls_us; + params.wls_us_kernel_va = (uint64_t)pWls_us->wls_us_kernel_va; + params.action = 0; + params.nMsg = 0; + + PLIB_DEBUG("WLS_Wait\n"); + + if((ret = ioctl(wls_dev_fd, WLS_IOC_WAIT, ¶ms)) < 0) { + PLIB_ERR("Wait filed [%d]\n", ret); + return ret; + } + + return params.nMsg; +} + +unsigned long long WLS_WGet(void* h, unsigned int *MsgSize, unsigned short *MsgTypeID, unsigned short *Flags) +{ + uint64_t pRxMsg = WLS_Get(h, MsgSize, MsgTypeID, Flags); + + if (pRxMsg) + return pRxMsg; + + WLS_Wait(h); + return WLS_Get(h, MsgSize, MsgTypeID, Flags); +} + +unsigned long long WLS_VA2PA(void* h, PVOID pMsg) +{ + uint64_t ret = 0; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + unsigned long alloc_base; + hugepage_tabl_t* pHugePageTlb; + uint64_t hugePageBase; + uint64_t hugePageOffet; + unsigned int count = 0; + + uint64_t HugePageMask = ((unsigned long)pWls_us->HugePageSize - 1); + + if(pWls_us->alloc_buffer == NULL){ + PLIB_ERR("WLS_VA2PA: nothing was allocated [%ld]\n", ret); + return (uint64_t)ret; + } + + alloc_base = (unsigned long)pWls_us->alloc_buffer; + + pHugePageTlb = &pWls_us->hugepageTbl[0]; + + hugePageBase = (uint64_t)pMsg & ~HugePageMask; + hugePageOffet = (uint64_t)pMsg & HugePageMask; + + count = (hugePageBase - alloc_base) / pWls_us->HugePageSize; + + PLIB_DEBUG("WLS_VA2PA %lx base %llx off %llx count %d\n", (unsigned long)pMsg, + (uint64_t)hugePageBase, (uint64_t)hugePageOffet, count); + + ret = pHugePageTlb[count].pagePa + hugePageOffet; + + return (uint64_t) ret; +} + +void* WLS_PA2VA(void* h, unsigned long long pMsg) +{ + unsigned long ret = NULL; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + hugepage_tabl_t* pHugePageTlb; + uint64_t hugePageBase; + uint64_t hugePageOffet; + unsigned int count; + int i; + uint64_t HugePageMask = ((uint64_t)pWls_us->HugePageSize - 1); + + if(pWls_us->alloc_buffer == NULL){ + PLIB_ERR("WLS_PA2VA: nothing was allocated [%ld]\n", ret); + return (void*)ret; + } + + pHugePageTlb = &pWls_us->hugepageTbl[0]; + + hugePageBase = (uint64_t)pMsg & ~HugePageMask; + hugePageOffet = (uint64_t)pMsg & HugePageMask; + + count = pWls_us->alloc_size / pWls_us->HugePageSize; + + PLIB_DEBUG("WLS_PA2VA %llx base %llx off %llx count %d\n", (uint64_t)pMsg, + (uint64_t)hugePageBase, (uint64_t)hugePageOffet, count); + + for (i = 0; i < count; i++) { + if (pHugePageTlb[i].pagePa == hugePageBase) + { + ret = (unsigned long)pHugePageTlb[i].pageVa; + ret += hugePageOffet; + return (void*)ret; + } + } + + return (void*) (ret); +} + +int WLS_EnqueueBlock(void* h, unsigned long long pMsg) +{ + int ret = 0; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + if (!wls_us_ctx || !wls_dev_fd){ + PLIB_ERR("Library was not opened\n"); + return -1; + } + + if(pWls_us->mode == WLS_SLAVE_CLIENT){ + PLIB_ERR("Slave doesn't support memory allocation\n"); + return -1; + } + + if(pMsg == 0){ + PLIB_ERR("WLS_EnqueueBlock: Null\n"); + return -1; + } + + if(pWls_us->dst_kernel_va){ + if (pWls_us->dst_user_va) + { + wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va; + ret = SFL_WlsEnqueue(&pDstWls_us->ul_free_block_pq, pMsg, wls_kernel_va_to_user_va_dest, pWls_us); + if(ret == 1){ + unsigned long* ptr = (unsigned long*)WLS_PA2VA(pWls_us, pMsg); + if(ptr){ + *ptr = 0xFFFFFFFFFFFFFFFF; + } + } + } + else + ret = -1; + } + else + ret = -1; + + PLIB_DEBUG("SFL_WlsEnqueue %d\n", ret); + return ret; +} + +unsigned long long WLS_DequeueBlock(void* h) +{ + unsigned long long retval = NULL; + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + + if(pWls_us->mode == WLS_SLAVE_CLIENT){ + // local + retval = SFL_WlsDequeue(&pWls_us->ul_free_block_pq, wls_kernel_va_to_user_va, h ); + } else if(pWls_us->dst_kernel_va) { + // remote + if (pWls_us->dst_user_va) + { + wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va; + retval = SFL_WlsDequeue(&pDstWls_us->ul_free_block_pq, wls_kernel_va_to_user_va_dest, pWls_us); + if(retval){ + unsigned long* ptr = (unsigned long*)WLS_PA2VA(pWls_us, retval); + if(ptr){ + if(*ptr != 0xFFFFFFFFFFFFFFFF){ + PLIB_ERR("WLS_EnqueueBlock: incorrect content pa: 0x%016lx: 0x%016lx\n", (unsigned long)retval, *ptr); + } + } + } + } + } + + return retval; +} + +int WLS_NumBlocks(void* h) +{ + wls_us_ctx_t* pWls_us = (wls_us_ctx_t* )h; + int n = 0; + + if(pWls_us->mode == WLS_SLAVE_CLIENT){ + // local + n = SFL_GetNumItemsInTheQueue(&pWls_us->ul_free_block_pq); + } else if(pWls_us->dst_kernel_va) { + // remote + if (pWls_us->dst_user_va) + { + wls_us_ctx_t* pDstWls_us = (wls_us_ctx_t* )pWls_us->dst_user_va; + n = SFL_GetNumItemsInTheQueue(&pDstWls_us->ul_free_block_pq); + } + } + + return n; +} + +