3f698848db4830f53e4204c7d2cff20b1c1f08b1
[o-du/phy.git] / wls_lib / test / mac / mac_wls.c
1 /******************************************************************************
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
19 /**
20  * @brief This file has Shared Memory interface functions between MAC and PHY
21  * @file testmac_wls.c
22  * @ingroup group_testmac
23  * @author Intel Corporation
24  **/
25
26
27 #include <sys/ioctl.h>
28 #include <pthread.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sched.h>
33 #include <unistd.h>
34 #include <string.h>
35
36 #include <rte_eal.h>
37 #include <rte_cfgfile.h>
38 #include <rte_string_fns.h>
39 #include <rte_common.h>
40 #include <rte_string_fns.h>
41 #include <rte_lcore.h>
42 #include <rte_debug.h>
43 #include <rte_launch.h>
44
45 #define DPDK_WLS
46 #include "wls.h"
47 #include "wls_lib.h"
48 #include "mac_wls.h"
49 //#include "phy_printf.h"
50 //#include "aux_sys.h"
51 //#include "aux_timer.h"
52 //#include "mlog_lnx.h"
53
54 //#include "nr5g_testmac_config_test.h"
55 //#include "nr5g_testmac_mac_phy_api_proc.h"
56
57
58 #define MSG_MAXSIZE                         ( 16384 * 16 )
59
60
61 #define TO_FREE_SIZE                        ( 10 )
62 #define TOTAL_FREE_BLOCKS                   ( 50 * 12)
63 #define ALLOC_TRACK_SIZE                    ( 16384 )
64
65 #define MEMORY_CORRUPTION_DETECT
66 #define MEMORY_CORRUPTION_DETECT_FLAG       (0xAB)
67
68 typedef struct wls_mac_mem_array
69 {
70     void **ppFreeBlock;
71     void *pStorage;
72     void *pEndOfStorage;
73     uint32_t nBlockSize;
74     uint32_t nBlockCount;
75 } WLS_MAC_MEM_SRUCT, *PWLS_MAC_MEM_SRUCT;
76
77 typedef struct wls_mac_ctx
78 {
79     void *hWls;
80     void *pWlsMemBase;
81     WLS_MAC_MEM_SRUCT sWlsStruct;
82
83     uint32_t nTotalMemorySize;
84     uint32_t nTotalBlocks;
85     uint32_t nAllocBlocks;
86     uint32_t nTotalAllocCnt;
87     uint32_t nTotalFreeCnt;
88     uint32_t nTotalUlBufAllocCnt;
89     uint32_t nTotalUlBufFreeCnt;
90     uint32_t nTotalDlBufAllocCnt;
91     uint32_t nTotalDlBufFreeCnt;
92 //  Support for FAPI Translator
93     uint32_t nPartitionMemSize;
94     void     *pPartitionMemBase;
95
96     volatile pthread_mutex_t lock;
97     volatile pthread_mutex_t lock_alloc;
98 } WLS_MAC_CTX, *PWLS_MAC_CTX;
99
100 static pthread_t *pwls_testmac_thread = NULL;
101 static WLS_MAC_CTX wls_mac_iface;
102 static int gwls_mac_ready = 0;
103 static pid_t gwls_pid = 0;
104 static uint32_t gToFreeListCnt[TO_FREE_SIZE] = {0};
105 static uint64_t gpToFreeList[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = {{0L}};
106 static uint8_t alloc_track[ALLOC_TRACK_SIZE];
107 static uint64_t gTotalTick = 0, gUsedTick = 0;
108
109 //-------------------------------------------------------------------------------------------
110 /** @ingroup group_testmac
111  *
112  *  @param[in]   ptr Pointer to display
113  *  @param[in]   size Size of data
114  *
115  *  @return  void
116  *
117  *  @description
118  *  This function displays content of Buffer - Used for debugging
119  *
120 **/
121 //-------------------------------------------------------------------------------------------
122 void wls_mac_show_data(void* ptr, uint32_t size)
123 {
124     uint8_t *d = ptr;
125     int i;
126
127     for(i = 0; i < size; i++)
128     {
129         if ( !(i & 0xf) )
130             printf("\n");
131         printf("%02x ", d[i]);
132     }
133     printf("\n");
134 }
135
136
137
138 //-------------------------------------------------------------------------------------------
139 /** @ingroup group_testmac
140  *
141  *  @param void
142  *
143  *  @return  Pointer to WLS_MAC_CTX stucture
144  *
145  *  @description
146  *  This function returns the WLS Local structure which has WLS related parameters
147  *
148 **/
149 //-------------------------------------------------------------------------------------------
150 static PWLS_MAC_CTX wls_mac_get_ctx(void)
151 {
152     return &wls_mac_iface;
153 }
154
155 void wls_mac_print_stats(void)
156 {
157     PWLS_MAC_CTX pWls = wls_mac_get_ctx();
158
159     printf("wls_mac_free_list_all:\n");
160     printf("        nTotalBlocks[%d] nAllocBlocks[%d] nFreeBlocks[%d]\n", pWls->nTotalBlocks, pWls->nAllocBlocks, (pWls->nTotalBlocks- pWls->nAllocBlocks));
161     printf("        nTotalAllocCnt[%d] nTotalFreeCnt[%d] Diff[%d]\n", pWls->nTotalAllocCnt, pWls->nTotalFreeCnt, (pWls->nTotalAllocCnt- pWls->nTotalFreeCnt));
162     printf("        nDlBufAllocCnt[%d] nDlBufFreeCnt[%d] Diff[%d]\n", pWls->nTotalDlBufAllocCnt, pWls->nTotalDlBufFreeCnt, (pWls->nTotalDlBufAllocCnt- pWls->nTotalDlBufFreeCnt));
163     printf("        nUlBufAllocCnt[%d] nUlBufFreeCnt[%d] Diff[%d]\n\n", pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt, (pWls->nTotalUlBufAllocCnt- pWls->nTotalUlBufFreeCnt));
164 }
165
166
167
168 //-------------------------------------------------------------------------------------------
169 /** @ingroup group_testmac
170  *
171  *  @param[in]   ptr Address to convert
172  *
173  *  @return  Converted address
174  *
175  *  @description
176  *  This function converts Virtual Address to Physical Address
177  *
178 **/
179 //-------------------------------------------------------------------------------------------
180 uint64_t wls_mac_va_to_pa(void *ptr)
181 {
182     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
183     uint64_t ret = (uint64_t)WLS_VA2PA(pWls->hWls, ptr);
184
185     //printf("wls_mac_va_to_pa: %p ->%p\n", ptr, (void*)ret);
186
187     return ret;
188 }
189
190
191
192 //-------------------------------------------------------------------------------------------
193 /** @ingroup group_testmac
194  *
195  *  @param[in]   ptr Address to convert
196  *
197  *  @return  Converted address
198  *
199  *  @description
200  *  This function converts Physical Address to Virtual Address
201  *
202 **/
203 //-------------------------------------------------------------------------------------------
204 void *wls_mac_pa_to_va(uint64_t ptr)
205 {
206     PWLS_MAC_CTX pWls = wls_mac_get_ctx();
207     void *ret = WLS_PA2VA(pWls->hWls, ptr);
208
209     //printf("wls_mac_pa_to_va: %p -> %p\n", (void*)ptr, ret);
210
211     return ret;
212 }
213
214
215
216 //-------------------------------------------------------------------------------------------
217 /** @ingroup group_testmac
218  *
219  *  @param[in]   pMemArray Pointer to WLS Memory management structure
220  *  @param[in]   pMemArrayMemory Pointer to flat buffer that was allocated
221  *  @param[in]   totalSize Total Size of flat buffer allocated
222  *  @param[in]   nBlockSize Size of each block that needs to be partitioned by memory manager
223  *
224  *  @return  0 if SUCCESS
225  *
226  *  @description
227  *  This function creates memory blocks from a flat buffer which will be used for communciation
228  *  between MAC and PHY
229  *
230 **/
231 //-------------------------------------------------------------------------------------------
232 uint32_t wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray,
233                               void *pMemArrayMemory,
234                               uint32_t totalSize, uint32_t nBlockSize)
235 {
236     int numBlocks = totalSize / nBlockSize;
237     void **ptr;
238     uint32_t i;
239
240     printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
241         pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
242
243     // Can't be less than pointer size
244     if (nBlockSize < sizeof(void *))
245     {
246         return FAILURE;
247     }
248
249     // Can't be less than one block
250     if (totalSize < sizeof(void *))
251     {
252         return FAILURE;
253     }
254
255     pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
256     pMemArray->pStorage = pMemArrayMemory;
257     pMemArray->pEndOfStorage = ((unsigned long*)pMemArrayMemory) + numBlocks * nBlockSize / sizeof(unsigned long);
258     pMemArray->nBlockSize = nBlockSize;
259     pMemArray->nBlockCount = numBlocks;
260
261     // Initialize single-linked list of free blocks;
262     ptr = (void **)pMemArrayMemory;
263     for (i = 0; i < pMemArray->nBlockCount; i++)
264     {
265 #ifdef MEMORY_CORRUPTION_DETECT
266         // Fill with some pattern
267         uint8_t *p = (uint8_t *)ptr;
268         uint32_t j;
269
270         p += (nBlockSize - 16);
271         for (j = 0; j < 16; j++)
272         {
273             p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
274         }
275 #endif
276
277         if (i == pMemArray->nBlockCount - 1)
278         {
279             *ptr = NULL;      // End of list
280         }
281         else
282         {
283             // Points to the next block
284             *ptr = (void **)(((uint8_t*)ptr) + nBlockSize);
285             ptr += nBlockSize / sizeof(unsigned long);
286         }
287     }
288
289     memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
290
291     return SUCCESS;
292 }
293
294
295
296
297 //-------------------------------------------------------------------------------------------
298 /** @ingroup group_testmac
299  *
300  *  @param[in]    pMemArray Pointer to WLS Memory management structure
301  *  @param[out]   ppBlock Pointer where allocated memory block is stored
302  *
303  *  @return  0 if SUCCESS
304  *
305  *  @description
306  *  This function allocated a memory block from pool
307  *
308 **/
309 //-------------------------------------------------------------------------------------------
310 uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock)
311 {
312     int idx;
313
314     if (pMemArray->ppFreeBlock == NULL)
315     {
316         printf("wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
317         return FAILURE;
318     }
319
320     // FIXME: Remove after debugging
321     if (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage) ||
322         ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))
323     {
324         printf("wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
325                 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
326         return FAILURE;
327     }
328
329     pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
330     *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
331
332     if ((*pMemArray->ppFreeBlock != NULL) &&
333         (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
334         ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage)))
335     {
336         fprintf(stderr, "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
337                 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
338                 *pMemArray->ppFreeBlock);
339         return FAILURE;
340     }
341
342     *ppBlock = (void *) pMemArray->ppFreeBlock;
343     pMemArray->ppFreeBlock = (void **) (*pMemArray->ppFreeBlock);
344
345     idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
346     if (alloc_track[idx])
347     {
348         printf("wls_mac_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
349             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
350             *pMemArray->ppFreeBlock);
351     }
352     else
353     {
354 #ifdef MEMORY_CORRUPTION_DETECT
355         uint32_t nBlockSize = pMemArray->nBlockSize, i;
356         uint8_t *p = (uint8_t *)*ppBlock;
357
358         p += (nBlockSize - 16);
359         for (i = 0; i < 16; i++)
360         {
361             p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
362         }
363 #endif
364         alloc_track[idx] = 1;
365     }
366
367     //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
368
369     return SUCCESS;
370 }
371
372
373
374
375 //-------------------------------------------------------------------------------------------
376 /** @ingroup group_testmac
377  *
378  *  @param[in]   pMemArray Pointer to WLS Memory management structure
379  *  @param[in]   pBlock Pointer to block that needs to be added back to pool
380  *
381  *  @return  0 if SUCCESS
382  *
383  *  @description
384  *  This function frees a WLS block of memory and adds it back to the pool
385  *
386 **/
387 //-------------------------------------------------------------------------------------------
388 uint32_t wls_mac_free_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pBlock)
389 {
390     int idx;
391     unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
392
393     pBlock = (void *)((unsigned long)pBlock & ~mask);
394
395     if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage))
396     {
397         printf("wls_mac_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
398                pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
399
400         return FAILURE;
401     }
402
403     idx = (int)(((uint64_t)pBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
404
405     if (alloc_track[idx] == 0)
406     {
407         printf("wls_mac_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
408             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
409             pBlock);
410
411         return SUCCESS;
412
413     }
414     else
415     {
416 #ifdef MEMORY_CORRUPTION_DETECT
417         uint32_t nBlockSize = pMemArray->nBlockSize, i;
418         uint8_t *p = (uint8_t *)pBlock;
419
420         p += (nBlockSize - 16);
421         for (i = 0; i < 16; i++)
422         {
423             if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG)
424             {
425                 printf("ERROR: Corruption\n");
426                 wls_mac_print_stats();
427                 exit(-1);
428             }
429         }
430 #endif
431         alloc_track[idx] = 0;
432     }
433
434     if (((void *) pMemArray->ppFreeBlock) == pBlock)
435     {
436         // Simple protection against freeing of already freed block
437         return SUCCESS;
438     }
439
440     // FIXME: Remove after debugging
441     if ((pMemArray->ppFreeBlock != NULL)
442         && (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage)
443         || ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)))
444     {
445         printf("wls_mac_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
446                 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
447         return FAILURE;
448     }
449
450     // FIXME: Remove after debugging
451     if ((pBlock < pMemArray->pStorage) ||
452         (pBlock >= pMemArray->pEndOfStorage))
453     {
454         printf("wls_mac_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
455                 pMemArray, pBlock);
456         return FAILURE;
457     }
458
459     *((void **)pBlock) = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
460     pMemArray->ppFreeBlock = (void **) ((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
461
462     //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
463
464     return SUCCESS;
465 }
466
467
468 //-------------------------------------------------------------------------------------------
469 /** @ingroup group_testmac
470  *
471  *  @param   void
472  *
473  *  @return  Pointer to the memory block
474  *
475  *  @description
476  *  This function allocates a block of memory from the pool
477  *
478 **/
479 //-------------------------------------------------------------------------------------------
480 void *wls_mac_alloc_buffer(uint32_t size, uint32_t loc)
481 {
482     void *pBlock = NULL;
483     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
484     PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
485
486     pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
487
488     if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS)
489     {
490         printf("wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
491         wls_mac_print_stats();
492         exit(-1);
493     }
494     else
495     {
496         pWls->nAllocBlocks++;
497     }
498
499     //printf("----------------wls_mac_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
500
501     //printf("[%p]\n", pBlock);
502
503     pWls->nTotalAllocCnt++;
504     if (loc < MAX_DL_BUF_LOCATIONS)
505         pWls->nTotalDlBufAllocCnt++;
506     else if (loc < MAX_UL_BUF_LOCATIONS)
507         pWls->nTotalUlBufAllocCnt++;
508
509     pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
510
511     return pBlock;
512 }
513
514
515
516 //-------------------------------------------------------------------------------------------
517 /** @ingroup group_testmac
518  *
519  *  @param[in]   *pMsg Pointer to free
520  *
521  *  @return  void
522  *
523  *  @description
524  *  This function frees a block of memory and adds it back to the pool
525  *
526 **/
527 //-------------------------------------------------------------------------------------------
528 void wls_mac_free_buffer(void *pMsg, uint32_t loc)
529 {
530     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
531     PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
532
533     pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
534
535     //printf("----------------wls_mac_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
536     if (wls_mac_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS)
537     {
538         pWls->nAllocBlocks--;
539     }
540     else
541     {
542         printf("wls_mac_free_buffer Free error\n");
543         wls_mac_print_stats();
544         exit(-1);
545     }
546
547     pWls->nTotalFreeCnt++;
548     if (loc < MAX_DL_BUF_LOCATIONS)
549         pWls->nTotalDlBufFreeCnt++;
550     else if (loc < MAX_UL_BUF_LOCATIONS)
551         pWls->nTotalUlBufFreeCnt++;
552
553     pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
554 }
555
556
557
558 //-------------------------------------------------------------------------------------------
559 /** @ingroup group_testmac
560  *
561  *  @param   void
562  *
563  *  @return  Number of free blocks
564  *
565  *  @description
566  *  This function queries the number of free blocks in the system
567  *
568 **/
569 //-------------------------------------------------------------------------------------------
570 int wls_mac_num_free_blocks(void)
571 {
572     PWLS_MAC_CTX pWls = wls_mac_get_ctx();
573
574     return (pWls->nTotalBlocks- pWls->nAllocBlocks);
575 }
576
577
578
579 void wls_mac_free_list_all(void)
580 {
581     PWLS_MAC_CTX pWls = wls_mac_get_ctx();
582     uint32_t idx;
583
584     for (idx = 0; idx < TO_FREE_SIZE; idx++)
585     {
586         wls_mac_free_list(idx);
587     }
588
589     wls_mac_print_stats();
590 }
591
592
593 //-------------------------------------------------------------------------------------------
594 /** @ingroup group_testmac
595  *
596  *  @param[in]   pWls Pointer to the WLS_MAC_CTX structure
597  *
598  *  @return  0 if SUCCESS
599  *
600  *  @description
601  *  This function created a partition and blocks of WLS memory for API exchange between MAC and PHY
602  *
603 **/
604 //-------------------------------------------------------------------------------------------
605 int wls_mac_create_partition(PWLS_MAC_CTX pWls)
606 {
607     memset(pWls->pWlsMemBase, 0xCC, pWls->nTotalMemorySize);
608     pWls->pPartitionMemBase = pWls->pWlsMemBase;
609     pWls->nPartitionMemSize = pWls->nTotalMemorySize/2;
610     pWls->nTotalBlocks = pWls->nTotalMemorySize / MSG_MAXSIZE;
611     return wls_mac_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase, pWls->nPartitionMemSize, MSG_MAXSIZE);
612 }
613
614
615
616 static volatile int gWlsMacPrintThreadInfo = 0;
617
618 void wls_mac_print_thread_info(void)
619 {
620     gWlsMacPrintThreadInfo = 1;
621
622     return;
623 }
624
625 void wls_mac_get_time_stats(uint64_t *pTotal, uint64_t *pUsed, uint32_t nClear)
626 {
627     *pTotal = gTotalTick;
628     *pUsed = gUsedTick;
629
630     if (nClear)
631     {
632         gTotalTick = 0;
633         gUsedTick = 0;
634     }
635 }
636
637 //-------------------------------------------------------------------------------------------
638 /** @ingroup group_testmac
639  *
640  *  @param[in]   pMsgHeader Pointer to TxSdu Message Block
641  *  @param[in]   count Location in Free List Array
642  *  @param[in]   pToFreeList Array where all the blocks to free are stored
643  *
644  *  @return  New Location in free list array
645  *
646  *  @description
647  *  This function adds all the messages in a subframe coming from L1 to L2 to a free array to be
648  *  freed back to the queue at a later point in time.
649  *
650 **/
651 //-------------------------------------------------------------------------------------------
652 int wls_mac_sdu_zbc_block_add_to_free(void* pMsgHeaderHead, int count, uint64_t *pToFreeList)
653 {
654     fapi_msg_t *p_fapi_msg = (fapi_msg_t *) pMsgHeaderHead;
655
656     if (p_fapi_msg->msg_id == FAPI_TX_DATA_REQUEST)
657     {
658         fapi_tx_data_req_t *p_tx_data_req =  (fapi_tx_data_req_t *) p_fapi_msg;
659         p_fapi_api_queue_elem_t p_list_elm = ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
660         p_fapi_api_queue_elem_t p_sdu_elm = p_list_elm->p_tx_data_elm_list;
661         while(p_sdu_elm)
662         {
663             if (count < TOTAL_FREE_BLOCKS)
664             {
665                 pToFreeList[count++] = (uint64_t) p_sdu_elm;
666             }
667             else
668             {
669                 printf("wls_mac_sdu_zbc_block_add_to_free: ERROR: Reached max Number of Free Blocks\n");
670                 return count;
671             }
672             p_sdu_elm = p_sdu_elm->p_next;
673         }
674     }
675
676     return count;
677 }
678
679
680 //-------------------------------------------------------------------------------------------
681 /** @ingroup group_testmac
682  *
683  *  @param[in]   pListElem Pointer to List element header
684  *  @param[in]   idx Subframe Number
685  *
686  *  @return  Number of blocks freed
687  *
688  *  @description
689  *  This function Frees all the blocks in a List Element Linked List coming from L1 by storing
690  *  them into an array to be freed at a later point in time.
691  *
692 **/
693 //-------------------------------------------------------------------------------------------
694 int wls_mac_add_to_free(p_fapi_api_queue_elem_t pListElem, uint32_t idx)
695 {
696     p_fapi_api_queue_elem_t pNextMsg = NULL;
697     void* pMsgHeader;
698     int count = gToFreeListCnt[idx], nZbcBlocks;
699
700     pNextMsg = pListElem;
701
702     while (pNextMsg)
703     {
704         if (count < TOTAL_FREE_BLOCKS)
705         {
706             gpToFreeList[idx][count] = (uint64_t)pNextMsg;
707         }
708         else
709         {
710             printf("wls_mac_add_to_free: ERROR: Reached max Number of Free Blocks\n");
711             return count;
712         }
713
714         if (pNextMsg->msg_type != FAPI_MSG_HEADER_IND)
715         {
716             pMsgHeader = (void *) (pNextMsg + 1);
717             count++;
718             count = wls_mac_sdu_zbc_block_add_to_free(pMsgHeader, count, gpToFreeList[idx]);
719         }
720
721         if (pNextMsg->p_next)
722         {
723             pNextMsg = (p_fapi_api_queue_elem_t)(pNextMsg->p_next);
724         }
725         else
726         {
727             pNextMsg = 0;
728         }
729     }
730
731     gpToFreeList[idx][count] = 0L;
732     gToFreeListCnt[idx] = count;
733
734     printf("To Free %d\n", count);
735
736     return count;
737 }
738
739
740 //-------------------------------------------------------------------------------------------
741 /** @ingroup group_testmac
742  *
743  *  @param[in]   idx subframe Number
744  *
745  *  @return  Number of blocks freed
746  *
747  *  @description
748  *  This function frees all blocks that have been added to the free array
749  *
750 **/
751 //-------------------------------------------------------------------------------------------
752 int wls_mac_free_list(uint32_t idx)
753 {
754     p_fapi_api_queue_elem_t pNextMsg = NULL;
755     int count = 0;
756
757     if(idx >= TO_FREE_SIZE){
758         printf("Error idx %d\n", idx);
759         return 0;
760     }
761
762     pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
763
764     while (pNextMsg)
765     {
766         wls_mac_free_buffer(pNextMsg, MIN_DL_BUF_LOCATIONS+0);
767         gpToFreeList[idx][count] = (uint64_t) NULL;
768         count++;
769         if (gpToFreeList[idx][count])
770             pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
771         else
772             pNextMsg = 0;
773     }
774
775     printf("Free %d\n", count);
776     gToFreeListCnt[idx] = 0;
777
778     return count;
779 }
780
781
782 //-------------------------------------------------------------------------------------------
783 /** @ingroup group_testmac
784  *
785  *  @param void
786  *
787  *  @return  0 if SUCCESS
788  *
789  *  @description
790  *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
791  *  needed by the L2
792  *
793 **/
794 //-------------------------------------------------------------------------------------------
795 int wls_mac_ready(void)
796 {
797     int ret = 0;
798     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
799     ret = WLS_Ready(pWls->hWls);
800
801     return ret;
802 }
803
804 //-------------------------------------------------------------------------------------------
805 /** @ingroup group_testmac
806  *
807  *  @param   void
808  *
809  *  @return  Number of blocks of APIs received
810  *
811  *  @description
812  *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
813  *  during runtime when L2 sends a API to L1 and then waits for response back.
814  *
815 **/
816 //-------------------------------------------------------------------------------------------
817 int wls_mac_wait(void)
818 {
819     int ret = 0;
820     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
821
822     ret = WLS_Wait(pWls->hWls);
823
824     return ret;
825 }
826
827 //-------------------------------------------------------------------------------------------
828 /** @ingroup group_testmac
829  *
830  *  @param[out]   data Location where First API from L1 is stored
831  *
832  *  @return  Size of Message sent from L1
833  *
834  *  @description
835  *  This function queries the APIs sent from L1 to L2 and gets the first pointer to the linked list
836  *
837 **/
838 //-------------------------------------------------------------------------------------------
839 uint32_t wls_mac_recv(uint64_t *data, uint16_t *nFlags)
840 {
841     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
842     uint32_t msgSize = 0;
843     uint16_t msgType = 0;
844
845     *data = WLS_Get(pWls->hWls, &msgSize, &msgType, nFlags);
846
847     return msgSize;
848 }
849
850
851 //-------------------------------------------------------------------------------------------
852 /** @ingroup group_testmac
853  *
854  *  @param[in]   pMsg Pointer to API block that needs to be sent to L1
855  *  @param[in]   MsgSize Size of Message
856  *  @param[in]   MsgTypeID Message Id
857  *  @param[in]   Flags Special Flags needed for WLS
858  *
859  *  @return  0 if SUCCESS
860  *
861  *  @description
862  *  This function adds a block of API from L2 to L1 which will be sent later
863  *
864 **/
865 //-------------------------------------------------------------------------------------------
866 int wls_mac_put(uint64_t pMsg, uint32_t MsgSize, uint16_t MsgTypeID, uint16_t Flags)
867 {
868     int ret = 0;
869     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
870
871     //printf("wls_mac_put: %p size: %d type: %d nFlags: %d\n", (void*)pMsg, MsgSize, MsgTypeID, Flags);
872     //  wls_mac_show_data((void*)wls_alloc_buffer(pMsg), MsgSize);
873     ret = WLS_Put(pWls->hWls, pMsg, MsgSize, MsgTypeID, Flags);
874
875     return ret;
876 }
877
878
879
880 //-------------------------------------------------------------------------------------------
881 /** @ingroup group_testmac
882  *
883  *  @param[in]   pMsgHeader Pointer to the TxSduReq Message block
884  *  @param[in]   nFlags Special nFlags needed for WLS
885  *  @param[in]   nZbcBlocks Number of ZBC blocks in list
886  *
887  *  @return  0 if SUCCESS
888  *
889  *  @description
890  *  This function adds all the ZBC blocks in a TXSDU Message and prepares them to be sent to the L1
891  *
892 **/
893 //-------------------------------------------------------------------------------------------
894 uint32_t wls_mac_send_zbc_blocks(void *pMsgHeaderHead, uint16_t nFlags, int *nZbcBlocks, uint32_t nFlagsUrllc)
895 {
896     fapi_tx_data_req_t *p_tx_data_req = (fapi_tx_data_req_t *) pMsgHeaderHead;
897     p_fapi_api_queue_elem_t p_list_elm = ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
898     p_list_elm = p_list_elm->p_tx_data_elm_list;
899
900     int ret = 0;
901     uint8_t nMsgType;
902     uint32_t isLast, nPduLen;
903     uint16_t list_flags = nFlags;
904     void *pPayload = NULL;
905
906     printf("wls_mac_put ZBC blocks: %d\n", nFlags);
907
908     while (p_list_elm)
909     {
910         nPduLen = p_list_elm->msg_len + sizeof(fapi_api_queue_elem_t);
911         pPayload = (void *) p_list_elm;
912         nMsgType = FAPI_MSG_PHY_ZBC_BLOCK_REQ;
913
914         if (p_list_elm->p_next)
915             isLast = 0;
916         else
917             isLast = 1;
918
919         if ((list_flags & WLS_TF_FIN) && isLast)
920             nFlags = WLS_SG_LAST; // TXSDU.req was last block in the list hence ZBC block is last
921         else
922             nFlags = WLS_SG_NEXT; // more blocks in the list
923
924         printf("wls_mac_put 0x%016lx  msg type: %x nFlags %x\n", (uint64_t) pPayload, nMsgType, nFlags);
925         ret = wls_mac_put((uint64_t) pPayload, nPduLen, nMsgType, nFlags);
926         if (ret != 0)
927         {
928             printf("Error ZBC block 0x%016lx\n", (uint64_t) pPayload);
929             return FAILURE;
930         }
931         p_list_elm = p_list_elm->p_next;
932     }
933
934     return SUCCESS;
935 }
936
937
938
939 //-------------------------------------------------------------------------------------------
940 /** @ingroup group_testmac
941  *
942  *  @param[in]    pMsgHeader Pointer to the TxSDuReq Message block
943  *  @param[out]   nZbcBlocks Number of ZBC blocks
944  *
945  *  @return  1 if this block is a TxSduReq message. 0 else.
946  *
947  *  @description
948  *  This function checks if a block is a TxSduReq messages and counts the number of ZBC blocks in this
949  *  API
950  *
951 **/
952 //-------------------------------------------------------------------------------------------
953 int wls_mac_is_sdu_zbc_block(void* pMsgHeaderHead, int *nZbcBlocks)
954 {
955     fapi_tx_data_req_t *p_tx_data_req = (fapi_tx_data_req_t *) pMsgHeaderHead;
956     p_fapi_api_queue_elem_t p_list_elm = 
957         ((p_fapi_api_queue_elem_t) p_tx_data_req) - 1;
958     *nZbcBlocks = 0;
959
960     if (p_tx_data_req->header.msg_id == FAPI_TX_DATA_REQUEST &&
961             p_list_elm->p_tx_data_elm_list)
962     {
963         return 1;
964     }
965
966     return 0;
967 }
968
969
970
971 //-------------------------------------------------------------------------------------------
972 /** @ingroup group_testmac
973  *
974  *  @param[in]   data Pointer to the Linked list header
975  *
976  *  @return  0 if SUCCESS
977  *
978  *  @description
979  *  This function sends a list of APIs to the L1
980  *
981 **/
982 //-------------------------------------------------------------------------------------------
983 uint32_t wls_mac_send_msg_to_phy(void *data)
984 {
985     uint32_t  ret = SUCCESS;
986     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
987     PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
988     p_fapi_api_queue_elem_t pCurrMsg = NULL;
989     p_fapi_api_queue_elem_t pListElem = NULL;
990     static uint32_t idx = 0;
991
992     fapi_msg_t *pMsgHeader;
993     uint16_t nFlags;
994     int nZbcBlocks = 0, isZbc = 0, count = 0;
995
996     printf("wls_mac_send_msg_to_phy\n");
997     printf("data (0x%lX) sending to phy...\n", (unsigned long)data);
998
999     pthread_mutex_lock((pthread_mutex_t *)&pWls->lock);
1000
1001     if (gwls_mac_ready)
1002     {
1003         pListElem = (p_fapi_api_queue_elem_t)data;
1004         wls_mac_add_to_free(pListElem, idx);
1005         count++;
1006
1007
1008         ret = wls_mac_put(wls_mac_va_to_pa(pListElem),
1009                 pListElem->msg_len + sizeof(fapi_api_queue_elem_t),
1010                 pMsgHeader->msg_id, nFlags);
1011         if (ret != 0)
1012         {
1013             printf("Error\n");
1014             pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1015             return FAILURE;
1016         }
1017     }
1018
1019     pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1020     return ret;
1021 }
1022
1023
1024 //-------------------------------------------------------------------------------------------
1025 /** @ingroup group_testmac
1026  *
1027  *  @param   void
1028  *
1029  *  @return  Number of blocks added
1030  *
1031  *  @description
1032  *  This function add WLS blocks to the L1 Array which will be used by L1 in every TTI to
1033  *  populate and send back APIs to the MAC
1034  *
1035 **/
1036 //-------------------------------------------------------------------------------------------
1037 int wls_mac_add_blocks_to_ul(void)
1038 {
1039     int ret = 0;
1040     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
1041
1042     void *pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+0);
1043
1044     if(pMsg)
1045     {
1046         /* allocate blocks for UL transmittion */
1047         while(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
1048         {
1049             ret++;
1050             pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
1051             if(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
1052             {
1053                 ret++;
1054                 pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
1055             }
1056
1057             if(!pMsg)
1058                 break;
1059         }
1060
1061         // free not enqueued block
1062         if(pMsg)
1063         {
1064             wls_mac_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS+3);
1065         }
1066     }
1067
1068     return ret;
1069 }
1070
1071
1072 //-------------------------------------------------------------------------------------------
1073 /** @ingroup group_testmac
1074  *
1075  *  @param[in]   data Thread Local Context Structure Pointer
1076  *
1077  *  @return  NULL
1078  *
1079  *  @description
1080  *  This is the WLS Receiver thread that is created at Testmac Init and is responsible for receiving
1081  *  APIs from L1 to MAC
1082  *
1083 **/
1084 //-------------------------------------------------------------------------------------------
1085 void *wls_mac_rx_task()
1086 {
1087     void*    buffer_va = 0;
1088     uint64_t      buffer_pa = 0;
1089     uint32_t get,i, rc = 0;
1090
1091     uint32_t size  = 0;
1092     uint64_t tWake = 0, tWakePrev = 0, tSleep = 0;
1093     uint16_t nFlags;
1094     p_fapi_api_queue_elem_t pElm   = NULL;
1095     p_fapi_api_queue_elem_t pFirst = NULL;
1096     p_fapi_api_queue_elem_t pPrev  = NULL;
1097
1098
1099     usleep(1000);
1100
1101     wls_mac_ready();
1102
1103     while (1)
1104     {
1105         get = wls_mac_wait();
1106
1107         if (get == 0)
1108         {
1109             continue;
1110         }
1111         printf("Got %d messages from FAPI Translator\n", get);
1112         while(get--)
1113         {
1114             size =  wls_mac_recv((uint64_t *)&buffer_pa, &nFlags);
1115             buffer_va =  wls_mac_pa_to_va(buffer_pa);
1116             pElm = (p_fapi_api_queue_elem_t) buffer_va;
1117
1118
1119             if (pFirst == NULL)
1120                 pFirst = pElm;
1121
1122             if (nFlags != WLS_TF_FIN)
1123             {
1124                 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pElm, i);
1125                 i++;
1126                                                 }
1127             if(pPrev)
1128                 pPrev->p_next = pElm;
1129
1130             pPrev = pElm;
1131
1132             if ((nFlags & WLS_TF_FIN))
1133             {
1134                 // send to MAC
1135                 if (pPrev)
1136                 {
1137                     pPrev->p_next =  NULL;
1138                 }
1139
1140                 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pFirst, i);
1141
1142                 pFirst= NULL;
1143                 pPrev = NULL;
1144                 return NULL;
1145             }
1146             else
1147             {
1148             }
1149         }
1150         wls_mac_add_blocks_to_ul();
1151
1152     }
1153
1154     return NULL;
1155 }
1156
1157 void wls_mac_print_recv_list(p_fapi_api_queue_elem_t list, uint32_t i)
1158 {
1159     printf("\nMAC received response %d from FAPI\n",i);
1160 }
1161
1162 p_fapi_api_queue_elem_t wls_mac_create_elem(uint16_t num_msg, uint32_t align_offset, uint32_t msg_type, uint32_t n_loc)
1163 {
1164     p_fapi_api_queue_elem_t p_list_elem;
1165
1166     p_list_elem = (p_fapi_api_queue_elem_t)wls_mac_alloc_buffer(num_msg * align_offset + sizeof(fapi_api_queue_elem_t), n_loc);
1167
1168     //Fill header for link list of API messages
1169     if (p_list_elem)
1170     {
1171         p_list_elem->msg_type = (uint8_t)msg_type;
1172         p_list_elem->num_message_in_block = 1;
1173         p_list_elem->align_offset = (uint16_t)align_offset;
1174         p_list_elem->msg_len = num_msg * align_offset;
1175         p_list_elem->p_next = NULL;
1176     }
1177
1178     return p_list_elem;
1179 }
1180
1181 //-------------------------------------------------------------------------------------------
1182 /** @ingroup group_testmac
1183  *
1184  *  @param   void
1185  *
1186  *  @return  0 if SUCCESS
1187  *
1188  *  @description
1189  *  This function initialized the WLS threads for the Testmac and allocates memory needed to
1190  *  exchange APIs between MAC and PHY
1191  *
1192 **/
1193 //-------------------------------------------------------------------------------------------
1194 uint32_t wls_mac_init(char * wls_device_name, uint64_t nTotalMemorySize)
1195 {
1196     uint32_t ret = FAILURE;
1197     PWLS_MAC_CTX pWls =  wls_mac_get_ctx();
1198     uint8_t *pMemZone;
1199     static const struct rte_memzone *mng_memzone;
1200     wls_drv_ctx_t *pDrv_ctx;
1201
1202     sleep(1);
1203
1204     pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
1205     pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
1206
1207     pWls->nTotalAllocCnt = 0;
1208     pWls->nTotalFreeCnt = 0;
1209     pWls->nTotalUlBufAllocCnt = 0;
1210     pWls->nTotalUlBufFreeCnt = 0;
1211     pWls->nTotalDlBufAllocCnt = 0;
1212     pWls->nTotalDlBufFreeCnt = 0;
1213
1214     pWls->hWls = WLS_Open(wls_device_name, WLS_MASTER_CLIENT, nTotalMemorySize);
1215     if (pWls->hWls)
1216     {
1217         /* allocate chuck of memory */
1218         pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nTotalMemorySize);
1219         if (pWls->pWlsMemBase)
1220         {
1221             pWls->nTotalMemorySize = (uint32_t) nTotalMemorySize;
1222
1223             ret = wls_mac_create_partition(pWls);
1224
1225             if (ret == SUCCESS)
1226             {
1227                 int nBlocks = 0;
1228                 gwls_mac_ready = 1;
1229
1230                 nBlocks = WLS_EnqueueBlock(pWls->hWls, wls_mac_va_to_pa(wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+2)));
1231                 /* allocate blocks for UL transmition */
1232                 while(WLS_EnqueueBlock(pWls->hWls, wls_mac_va_to_pa(wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+3))))
1233                 {
1234                     nBlocks++;
1235                 }
1236
1237                 printf("WLS inited ok [%d]\n\n", nBlocks);
1238             }
1239             else
1240             {
1241                 printf("can't create WLS Partition");
1242                 return FAILURE;
1243             }
1244
1245         }
1246         else
1247         {
1248             printf("can't allocate WLS memory");
1249             return FAILURE;
1250         }
1251     }
1252     else
1253     {
1254         printf("can't open WLS instance");
1255         return FAILURE;
1256     }
1257
1258     return SUCCESS;
1259 }
1260
1261
1262 //-------------------------------------------------------------------------------------------
1263 /** @ingroup group_testmac
1264  *
1265  *  @param   void
1266  *
1267  *  @return  0 if SUCCESS
1268  *
1269  *  @description
1270  *  This function destroys the WLS layer for the testmac and de-allocates any memory used
1271  *
1272 **/
1273 //-------------------------------------------------------------------------------------------
1274 uint32_t wls_mac_destroy(void)
1275 {
1276     PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1277
1278     if (pwls_testmac_thread)
1279     {
1280         pthread_cancel(*pwls_testmac_thread);
1281
1282         free(pwls_testmac_thread);
1283         pwls_testmac_thread = NULL;
1284
1285         if(pWls->pWlsMemBase)
1286         {
1287             WLS_Free(pWls->hWls, pWls->pWlsMemBase);
1288         }
1289
1290         WLS_Close(pWls->hWls);
1291         printf("wls_mac_rx_task:          [PID: %6d]... Stopping\n", gwls_pid);
1292     }
1293
1294     return SUCCESS;
1295 }
1296
1297 uint8_t mac_dpdk_init()
1298 {
1299     uint8_t retval;
1300     char whitelist[32];
1301     uint8_t i;
1302
1303     char *argv[] = {"mac_app", "--proc-type=secondary",
1304         "--file-prefix", "wls", whitelist};
1305     
1306     int argc = RTE_DIM(argv);
1307
1308     /* initialize EAL first */
1309     sprintf(whitelist, "-w %s",  "0000:00:06.0");
1310     printf("[MAC] Calling rte_eal_init: ");
1311
1312     for (i = 0; i < RTE_DIM(argv); i++)
1313     {
1314         printf("%s ", argv[i]);
1315     }
1316     printf("\n");
1317
1318     if (rte_eal_init(argc, argv) < 0)
1319         rte_panic("Cannot init EAL\n");
1320
1321     return SUCCESS;
1322 }