blob: 3bedeed9b592bcc24a7ccc583e62304893b87345 [file] [log] [blame]
Luis Farias9d66fca2020-05-28 19:01:58 -07001/******************************************************************************
2*
3* Copyright (c) 2019 Intel.
4*
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
8*
9* http://www.apache.org/licenses/LICENSE-2.0
10*
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.
16*
17*******************************************************************************/
18#ifdef __KERNEL__
19#include <linux/slab.h>
20#include <linux/kernel.h>
21#else
22#include <stdio.h>
23#include <string.h>
24#endif
25#include "syslib.h"
26#include "wls.h"
27
28#ifdef __KERNEL__
29#ifdef _DEBUG_
30#define PRINT_DEBUG(format, args...) \
31do { \
32 printk(KERN_INFO "wls debug: " format,##args); \
33}while(0)
34#else
35#define PRINT_DEBUG(x, args...) do { } while(0)
36#endif
37#else
38#ifdef _DEBUG_
39#define PRINT_DEBUG(x, args...) printf("wls_lib debug: "x, ## args);
40#else
41#define PRINT_DEBUG(x, args...) do { } while(0)
42#endif
43#endif
44
45
46
47#define SFL_memcpy memcpy
48/******************************************************************************
49* *
50* Generic fast queue that operates with pointers (derived from ICC) *
51* *
52******************************************************************************/
53
54int SFL_WlsEnqueue(PFASTQUEUE pq, U64 pData, wls_us_addr_conv change_addr, void* hWls)
55{
56 U32 put = pq->put;
57 U32 new_put = put + 1;
58
59 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);
60
61 if (new_put >= pq->size)
62 new_put = 0;
63
64 if (new_put != pq->get)
65 { // the queue is not full
66
67 U64* pLocalStorage = (U64*) pq->pStorage; // kernel VA
68 if (change_addr)
69 pLocalStorage = (U64*)change_addr(hWls, (U64)pq->pStorage); // user VA
70
71 PRINT_DEBUG("pLocalStorage %lx\n", (U64)pLocalStorage);
72
73 pLocalStorage[put] = pData;
74
75 DSB();
76 pq->put = new_put;
77 return TRUE;
78 }
79 return FALSE;
80}
81
82
83U64 SFL_WlsDequeue(PFASTQUEUE pq,
84 wls_us_addr_conv change_addr,
85 void *hWls)
86{
87 U64 p;
88 U32 get = pq->get;
89
90 if ((pq->put - get) != 0)
91 {
92 U64* pLocalStorage = (U64*) pq->pStorage; // kernel VA
93
94 DSB();
95 if (change_addr)
96 pLocalStorage = (U64 *)change_addr(hWls, (U64)pLocalStorage); //convert to user VA
97
98 p = pLocalStorage[get++];
99 if (get >= pq->size)
100 get = 0;
101
102 pq->get = get;
103 return p;
104 }
105 return 0;
106}
107
108/*
109int SFL_Enqueue_NoSync(PFASTQUEUE pq, PVOID pData)
110{
111 U32 put = pq->put;
112 U32 new_put = put + 1;
113 if (new_put >= pq->size)
114 new_put = 0;
115
116 if (new_put != pq->get)
117 { // the queue is not full
118 pq->pStorage[ put ] = pData;
119 pq->put = new_put;
120 return TRUE;
121 }
122 return FALSE;
123}*/
124
125/*
126PVOID SFL_Dequeue_NoSync(PFASTQUEUE pq)
127{
128 PVOID p;
129 U32 get = pq->get;
130
131 if ((pq->put - get) != 0)
132 {
133 p = pq->pStorage[get++];
134 if (get >= pq->size)
135 get = 0;
136 pq->get = get;
137 return p;
138 }
139 return NULL;
140}*/
141
142void SFL_DefQueue(PFASTQUEUE pq, void *pStorage, int StorageSize)
143{
144 memset( (void*) pq, 0x00, sizeof( FASTQUEUE) );
145 // always define storage as U64 []
146 pq->size = StorageSize >> 3;
147 pq->pStorage = (U64)pStorage;
148
149 PRINT_DEBUG("put %d get %d size %d pq->pStorage %lx\n",pq->put, pq->get, pq->size, pq->pStorage);
150
151}
152
153static U32 sfl_SafeQueueLevel(U32 put, U32 get, U32 size)
154{
155 U32 nItems;
156
157 if (put >= get)
158 nItems = put - get;
159 else
160 nItems = size + put - get;
161
162 return nItems;
163}
164
165U32 WLS_GetNumItemsInTheQueue(PWLS_MSG_QUEUE fpq)
166{
167 return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
168}
169
170U32 SFL_GetNumItemsInTheQueue(FASTQUEUE *fpq)
171{
172 return sfl_SafeQueueLevel(fpq->put, fpq->get, fpq->size);
173}
174
175/*
176
177U32 SFL_Queue_BatchRead( PFASTQUEUE pq, unsigned long *pDestArr, U32 Count)
178{
179 if (Count)
180 {
181 U32 write_index = 0;
182 U32 nReads = 0;
183 //U32 iMask = SFL_IDisable();
184 U32 put = pq->put; // fetch the put atomicly (as app may change it!)
185 U32 get = pq->get; // cache the volatile "get index"
186
187 //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
188
189 if ( (nReads = sfl_SafeQueueLevel(put, get, pq->size)) < Count )
190 Count = nReads;
191 else
192 nReads = Count;
193
194 if (Count >= pq->size - get)
195 {
196 U32 n = pq->size - get;
197 SFL_memcpy( pDestArr, &pq->pStorage[get], sizeof(pDestArr[0]) * n);
198 get = 0;
199 Count -= n;
200 write_index += n;
201 }
202
203 if (Count)
204 {
205 SFL_memcpy( &pDestArr[write_index], &pq->pStorage[get], sizeof(pDestArr[0]) * Count);
206 get += Count;
207 }
208
209 DSB();
210 pq->get = get;
211
212 //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
213
214 //SFL_IControl(iMask);
215
216 return nReads;
217 }
218 return FALSE;
219}
220
221
222// the routine does not keep the fifo order (it is used to take items away from the queue)
223U32 SFL_Queue_BatchUnload(PFASTQUEUE pq, unsigned long* pDestArr, U32 Count)
224{
225 if (Count)
226 {
227 U32 write_index = 0;
228 U32 nReads = 0;
229 //U32 iMask = SFL_IDisable();
230 U32 put = pq->put; // lets cache the volatile "put index"
231 U32 get = pq->get; // fetch the get index atomicly (as app may change it)
232
233 //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
234
235 nReads = sfl_SafeQueueLevel(put, get, pq->size);
236 if (nReads)
237 nReads -= 1; // decrement is used to cover the case when a reader already started reading from head
238
239 if ( nReads < Count )
240 Count = nReads;
241 else
242 nReads = Count;
243
244 if (!put)
245 put = pq->size;
246
247 if (Count >= put)
248 {
249 U32 n = put;
250 SFL_memcpy( pDestArr, &pq->pStorage[0], sizeof(pDestArr[0]) * n);
251 put = pq->size;
252 Count -= n;
253 write_index += n;
254 }
255
256 if (Count)
257 {
258 put -= Count;
259 SFL_memcpy( &pDestArr[write_index], &pq->pStorage[put], sizeof(pDestArr[0]) * Count);
260 }
261
262 if (put >= pq->size)
263 put = 0;
264
265 DSB();
266 pq->put = put;
267
268 //printf("nItems_%d ", SFL_GetNumItemsInTheQueue(pq));
269
270 //SFL_IControl(iMask);
271
272 return nReads;
273 }
274 return FALSE;
275}
276
277
278U32 SFL_Queue_BatchWrite( PFASTQUEUE pq, unsigned long *pSrcArr, U32 Count)
279{
280
281 U32 nWrites = Count;
282
283 if (Count)
284 {
285 U32 read_index = 0;
286 U32 put = pq->put;
287 //U32 iMask = SFL_IDisable();
288
289 if (pq->size - put <= Count)
290 {
291 U32 n = pq->size - put;
292 SFL_memcpy( &pq->pStorage[put], pSrcArr, sizeof(pSrcArr[0]) * n);
293 put = 0;
294 Count -= n;
295 read_index += n;
296 }
297
298 if (Count)
299 {
300 SFL_memcpy( &pq->pStorage[put], &pSrcArr[read_index], sizeof(pSrcArr[0]) * Count);
301 put += Count;
302 }
303
304 DSB();
305 pq->put = put;
306
307 //SFL_IControl(iMask);
308 return nWrites;
309 }
310 return 0;
311}
312*/
313void WLS_MsgDefineQueue(
314 PWLS_MSG_QUEUE pq,
315 PWLS_MSG_HANDLE pStorage,
316 U32 size,
317 U32 sema)
318{
319 memset( pq, 0x00, sizeof(WLS_MSG_QUEUE));
320 pq->pStorage = (U64) pStorage;
321 pq->get = 0;
322 pq->put = 0;
323 pq->size = size; // number of items
324 pq->sema = sema;
325}
326
327U32 WLS_MsgEnqueue(
328 PWLS_MSG_QUEUE pq,
329 U64 pIaPaMsg,
330 U32 MsgSize,
331 U16 TypeID,
332 U16 flags,
333 wls_us_addr_conv change_addr,
334 void *hWls)
335{
336 U32 rc = 0;
337 // below is protected section.
338 U32 put = pq->put;
339 U32 put_new = put + 1;
340
341 if (put_new >= pq->size)
342 put_new = 0;
343
344 if (put_new != pq->get)
345 {
346 PWLS_MSG_HANDLE pLocalStorage = (PWLS_MSG_HANDLE)pq->pStorage; // kernel VA
347 PWLS_MSG_HANDLE pItem;
348
349 PRINT_DEBUG("Kernel VA pq->pStorage %lx put [%d] %d %d\n", pq->pStorage, put_new, pq->get, pq->size);
350
351 if (change_addr)
352 pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64)pq->pStorage);
353
354 pItem = &pLocalStorage[put];
355
356 pItem->pIaPaMsg = pIaPaMsg;
357 pItem->MsgSize = MsgSize;
358 pItem->TypeID = TypeID;
359 pItem->flags = flags;
360 DSB();
361 pq->put = put_new;
362 rc = 1;
363 }
364
365 return rc;
366}
367
368int WLS_MsgDequeue(
369 PWLS_MSG_QUEUE pq,
370 PWLS_MSG_HANDLE pDestItem,
371 wls_us_addr_conv change_addr,
372 void *hWls)
373{
374 int retval = FALSE;
375 U32 get = pq->get;
376 PWLS_MSG_HANDLE pLocalStorage;
377
378 if (!pDestItem)
379 return retval;
380
381 if (get >= pq->size)
382 {
383
384 PRINT_DEBUG("error WLS_MsgDequeue get %d size %d\n", get, pq->size);
385
386 return retval;
387 }
388
389 pLocalStorage = (PWLS_MSG_HANDLE) pq->pStorage; // kernel VA
390 PRINT_DEBUG("WLS_MsgDequeue with pq->pStorage %lX\n",pq->pStorage);
391 if (pq->put != get)
392 {
393
394 DSB();
395 if (change_addr)
396 pLocalStorage = (PWLS_MSG_HANDLE)change_addr(hWls, (U64) pq->pStorage); //convert to user VA
397
398 *pDestItem = pLocalStorage[get];
399
400 if (++get == pq->size)
401 get = 0;
402
403 pq->get = get;
404 retval = TRUE;
405 }
406
407 return retval;
408}