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