--- /dev/null
+/******************************************************************************
+*
+* 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.
+*
+*******************************************************************************/
+#ifdef __KERNEL__
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "syslib.h"
+#include "wls.h"
+
+#ifdef __KERNEL__
+#ifdef _DEBUG_
+#define PRINT_DEBUG(format, args...) \
+do { \
+ printk(KERN_INFO "wls debug: " format,##args); \
+}while(0)
+#else
+#define PRINT_DEBUG(x, args...) do { } while(0)
+#endif
+#else
+#ifdef _DEBUG_
+#define PRINT_DEBUG(x, args...) printf("wls_lib debug: "x, ## args);
+#else
+#define PRINT_DEBUG(x, args...) do { } while(0)
+#endif
+#endif
+
+
+
+#define SFL_memcpy memcpy
+/******************************************************************************
+* *
+* Generic fast queue that operates with pointers (derived from ICC) *
+* *
+******************************************************************************/
+
+int SFL_WlsEnqueue(PFASTQUEUE pq, U64 pData, wls_us_addr_conv change_addr, void* hWls)
+{
+ U32 put = pq->put;
+ U32 new_put = put + 1;
+
+ PRINT_DEBUG("off %lx put %d get %d size %d storage %lx\n",(unsigned long)pq - (unsigned long) hWls, pq->put, pq->get, pq->size, pq->pStorage);
+
+ if (new_put >= pq->size)
+ new_put = 0;
+
+ if (new_put != pq->get)
+ { // the queue is not full
+
+ U64* pLocalStorage = (U64*) pq->pStorage; // kernel VA
+ if (change_addr)
+ pLocalStorage = (U64*)change_addr(hWls, (U64)pq->pStorage); // user VA
+
+ PRINT_DEBUG("pLocalStorage %lx\n", (U64)pLocalStorage);
+
+ pLocalStorage[put] = pData;
+
+ DSB();
+ pq->put = new_put;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+U64 SFL_WlsDequeue(PFASTQUEUE pq,
+ wls_us_addr_conv change_addr,
+ void *hWls)
+{
+ U64 p;
+ U32 get = pq->get;
+
+ if ((pq->put - get) != 0)
+ {
+ U64* pLocalStorage = (U64*) pq->pStorage; // kernel VA
+
+ DSB();
+ if (change_addr)
+ pLocalStorage = (U64 *)change_addr(hWls, (U64)pLocalStorage); //convert to user VA
+
+ p = pLocalStorage[get++];
+ if (get >= pq->size)
+ get = 0;
+
+ pq->get = get;
+ return p;
+ }
+ return 0;
+}
+
+/*
+int SFL_Enqueue_NoSync(PFASTQUEUE pq, PVOID pData)
+{
+ U32 put = pq->put;
+ U32 new_put = put + 1;
+ if (new_put >= pq->size)
+ new_put = 0;
+
+ if (new_put != pq->get)
+ { // the queue is not full
+ pq->pStorage[ put ] = pData;
+ pq->put = new_put;
+ return TRUE;
+ }
+ return FALSE;
+}*/
+
+/*
+PVOID SFL_Dequeue_NoSync(PFASTQUEUE pq)
+{
+ PVOID p;
+ U32 get = pq->get;
+
+ if ((pq->put - get) != 0)
+ {
+ p = pq->pStorage[get++];
+ if (get >= pq->size)
+ get = 0;
+ pq->get = get;
+ return p;
+ }
+ return NULL;
+}*/
+
+void SFL_DefQueue(PFASTQUEUE pq, void *pStorage, int StorageSize)
+{
+ memset( (void*) pq, 0x00, sizeof( FASTQUEUE) );
+ // always define storage as U64 []
+ pq->size = StorageSize >> 3;
+ pq->pStorage = (U64)pStorage;
+
+ PRINT_DEBUG("put %d get %d size %d pq->pStorage %lx\n",pq->put, pq->get, pq->size, pq->pStorage);
+
+}
+
+static U32 sfl_SafeQueueLevel(U32 put, U32 get, U32 size)
+{
+ U32 nItems;
+
+ if (put >= get)
+ nItems = put - get;
+ else
+ nItems = size + put - get;
+
+ return nItems;
+}
+
+U32 WLS_GetNumItemsInTheQueue(PWLS_MSG_QUEUE fpq)
+{
+ return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
+}
+
+U32 SFL_GetNumItemsInTheQueue(FASTQUEUE *fpq)
+{
+ return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
+}
+
+/*
+
+U32 SFL_Queue_BatchRead( PFASTQUEUE pq, unsigned long *pDestArr, U32 Count)
+{
+ if (Count)
+ {
+ U32 write_index = 0;
+ U32 nReads = 0;
+ //U32 iMask = SFL_IDisable();
+ U32 put = pq->put; // fetch the put atomicly (as app may change it!)
+ U32 get = pq->get; // cache the volatile "get index"
+
+ //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+ if ( (nReads = sfl_SafeQueueLevel(put, get, pq->size)) < Count )
+ Count = nReads;
+ else
+ nReads = Count;
+
+ if (Count >= pq->size - get)
+ {
+ U32 n = pq->size - get;
+ SFL_memcpy( pDestArr, &pq->pStorage[get], sizeof(pDestArr[0]) * n);
+ get = 0;
+ Count -= n;
+ write_index += n;
+ }
+
+ if (Count)
+ {
+ SFL_memcpy( &pDestArr[write_index], &pq->pStorage[get], sizeof(pDestArr[0]) * Count);
+ get += Count;
+ }
+
+ DSB();
+ pq->get = get;
+
+ //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+ //SFL_IControl(iMask);
+
+ return nReads;
+ }
+ return FALSE;
+}
+
+
+// the routine does not keep the fifo order (it is used to take items away from the queue)
+U32 SFL_Queue_BatchUnload(PFASTQUEUE pq, unsigned long* pDestArr, U32 Count)
+{
+ if (Count)
+ {
+ U32 write_index = 0;
+ U32 nReads = 0;
+ //U32 iMask = SFL_IDisable();
+ U32 put = pq->put; // lets cache the volatile "put index"
+ U32 get = pq->get; // fetch the get index atomicly (as app may change it)
+
+ //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+ nReads = sfl_SafeQueueLevel(put, get, pq->size);
+ if (nReads)
+ nReads -= 1; // decrement is used to cover the case when a reader already started reading from head
+
+ if ( nReads < Count )
+ Count = nReads;
+ else
+ nReads = Count;
+
+ if (!put)
+ put = pq->size;
+
+ if (Count >= put)
+ {
+ U32 n = put;
+ SFL_memcpy( pDestArr, &pq->pStorage[0], sizeof(pDestArr[0]) * n);
+ put = pq->size;
+ Count -= n;
+ write_index += n;
+ }
+
+ if (Count)
+ {
+ put -= Count;
+ SFL_memcpy( &pDestArr[write_index], &pq->pStorage[put], sizeof(pDestArr[0]) * Count);
+ }
+
+ if (put >= pq->size)
+ put = 0;
+
+ DSB();
+ pq->put = put;
+
+ //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
+
+ //SFL_IControl(iMask);
+
+ return nReads;
+ }
+ return FALSE;
+}
+
+
+U32 SFL_Queue_BatchWrite( PFASTQUEUE pq, unsigned long *pSrcArr, U32 Count)
+{
+
+ U32 nWrites = Count;
+
+ if (Count)
+ {
+ U32 read_index = 0;
+ U32 put = pq->put;
+ //U32 iMask = SFL_IDisable();
+
+ if (pq->size - put <= Count)
+ {
+ U32 n = pq->size - put;
+ SFL_memcpy( &pq->pStorage[put], pSrcArr, sizeof(pSrcArr[0]) * n);
+ put = 0;
+ Count -= n;
+ read_index += n;
+ }
+
+ if (Count)
+ {
+ SFL_memcpy( &pq->pStorage[put], &pSrcArr[read_index], sizeof(pSrcArr[0]) * Count);
+ put += Count;
+ }
+
+ DSB();
+ pq->put = put;
+
+ //SFL_IControl(iMask);
+ return nWrites;
+ }
+ return 0;
+}
+*/
+void WLS_MsgDefineQueue(
+ PWLS_MSG_QUEUE pq,
+ PWLS_MSG_HANDLE pStorage,
+ U32 size,
+ U32 sema)
+{
+ memset( pq, 0x00, sizeof(WLS_MSG_QUEUE));
+ pq->pStorage = (U64) pStorage;
+ pq->get = 0;
+ pq->put = 0;
+ pq->size = size; // number of items
+ pq->sema = sema;
+}
+
+U32 WLS_MsgEnqueue(
+ PWLS_MSG_QUEUE pq,
+ U64 pIaPaMsg,
+ U32 MsgSize,
+ U16 TypeID,
+ U16 flags,
+ wls_us_addr_conv change_addr,
+ void *hWls)
+{
+ U32 rc = 0;
+ // below is protected section.
+ U32 put = pq->put;
+ U32 put_new = put + 1;
+
+ if (put_new >= pq->size)
+ put_new = 0;
+
+ if (put_new != pq->get)
+ {
+ PWLS_MSG_HANDLE pLocalStorage = (PWLS_MSG_HANDLE)pq->pStorage; // kernel VA
+ PWLS_MSG_HANDLE pItem;
+
+ PRINT_DEBUG("Kernel VA pq->pStorage %lx put [%d] %d %d\n", pq->pStorage, put_new, pq->get, pq->size);
+
+ if (change_addr)
+ pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64)pq->pStorage);
+
+ pItem = &pLocalStorage[put];
+
+ pItem->pIaPaMsg = pIaPaMsg;
+ pItem->MsgSize = MsgSize;
+ pItem->TypeID = TypeID;
+ pItem->flags = flags;
+ DSB();
+ pq->put = put_new;
+ rc = 1;
+ }
+
+ return rc;
+}
+
+int WLS_MsgDequeue(
+ PWLS_MSG_QUEUE pq,
+ PWLS_MSG_HANDLE pDestItem,
+ wls_us_addr_conv change_addr,
+ void *hWls)
+{
+ int retval = FALSE;
+ U32 get = pq->get;
+ PWLS_MSG_HANDLE pLocalStorage;
+
+ if (!pDestItem)
+ return retval;
+
+ if (get >= pq->size)
+ {
+
+ PRINT_DEBUG("error WLS_MsgDequeue get %d size %d\n", get, pq->size);
+
+ return retval;
+ }
+
+ pLocalStorage = (PWLS_MSG_HANDLE) pq->pStorage; // kernel VA
+ PRINT_DEBUG("WLS_MsgDequeue with pq->pStorage %lX\n",pq->pStorage);
+ if (pq->put != get)
+ {
+
+ DSB();
+ if (change_addr)
+ pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64) pq->pStorage); //convert to user VA
+
+ *pDestItem = pLocalStorage[get];
+
+ if (++get == pq->size)
+ get = 0;
+
+ pq->get = get;
+ retval = TRUE;
+ }
+
+ return retval;
+}