1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 *******************************************************************************/
20 * @brief This file has Shared Memory interface functions between MAC and PHY
22 * @ingroup group_testmac
23 * @author Intel Corporation
27 #include <sys/ioctl.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>
49 //#include "phy_printf.h"
50 //#include "aux_sys.h"
51 //#include "aux_timer.h"
52 //#include "mlog_lnx.h"
54 //#include "nr5g_testmac_config_test.h"
55 //#include "nr5g_testmac_mac_phy_api_proc.h"
58 #define MSG_MAXSIZE ( 16384 * 16 )
61 #define TO_FREE_SIZE ( 10 )
62 #define TOTAL_FREE_BLOCKS ( 50 * 12)
63 #define ALLOC_TRACK_SIZE ( 16384 )
65 //#define MEMORY_CORRUPTION_DETECT
66 #define MEMORY_CORRUPTION_DETECT_FLAG (0xAB)
68 typedef struct wls_mac_mem_array
75 } WLS_MAC_MEM_SRUCT, *PWLS_MAC_MEM_SRUCT;
77 typedef struct wls_mac_ctx
81 void *pWlsMemBaseUsable;
82 WLS_MAC_MEM_SRUCT sWlsStruct;
84 uint64_t nTotalMemorySize;
85 uint64_t nTotalMemorySizeUsable;
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;
99 volatile pthread_mutex_t lock;
100 volatile pthread_mutex_t lock_alloc;
101 } WLS_MAC_CTX, *PWLS_MAC_CTX;
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;
112 //-------------------------------------------------------------------------------------------
113 /** @ingroup group_testmac
115 * @param[in] ptr Pointer to display
116 * @param[in] size Size of data
121 * This function displays content of Buffer - Used for debugging
124 //-------------------------------------------------------------------------------------------
125 void wls_mac_show_data(void* ptr, uint32_t size)
130 for(i = 0; i < size; i++)
134 printf("%02x ", d[i]);
141 //-------------------------------------------------------------------------------------------
142 /** @ingroup group_testmac
146 * @return Pointer to WLS_MAC_CTX stucture
149 * This function returns the WLS Local structure which has WLS related parameters
152 //-------------------------------------------------------------------------------------------
153 static PWLS_MAC_CTX wls_mac_get_ctx(void)
155 return &wls_mac_iface;
158 void wls_mac_print_stats(void)
160 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
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));
171 //-------------------------------------------------------------------------------------------
172 /** @ingroup group_testmac
174 * @param[in] ptr Address to convert
176 * @return Converted address
179 * This function converts Virtual Address to Physical Address
182 //-------------------------------------------------------------------------------------------
183 uint64_t wls_mac_va_to_pa(void *ptr)
185 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
186 uint64_t ret = (uint64_t)WLS_VA2PA(pWls->hWls, ptr);
188 //printf("wls_mac_va_to_pa: %p ->%p\n", ptr, (void*)ret);
195 //-------------------------------------------------------------------------------------------
196 /** @ingroup group_testmac
198 * @param[in] ptr Address to convert
200 * @return Converted address
203 * This function converts Physical Address to Virtual Address
206 //-------------------------------------------------------------------------------------------
207 void *wls_mac_pa_to_va(uint64_t ptr)
209 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
210 void *ret = WLS_PA2VA(pWls->hWls, ptr);
212 //printf("wls_mac_pa_to_va: %p -> %p\n", (void*)ptr, ret);
219 //-------------------------------------------------------------------------------------------
220 /** @ingroup group_testmac
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
227 * @return 0 if SUCCESS
230 * This function creates memory blocks from a flat buffer which will be used for communciation
231 * between MAC and PHY
234 //-------------------------------------------------------------------------------------------
235 uint32_t wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray,
236 void *pMemArrayMemory,
237 uint32_t totalSize, uint32_t nBlockSize)
239 int numBlocks = totalSize / nBlockSize;
243 printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
244 pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
246 // Can't be less than pointer size
247 if (nBlockSize < sizeof(void *))
252 // Can't be less than one block
253 if (totalSize < sizeof(void *))
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;
264 // Initialize single-linked list of free blocks;
265 ptr = (void **)pMemArrayMemory;
266 for (i = 0; i < pMemArray->nBlockCount; i++)
268 #ifdef MEMORY_CORRUPTION_DETECT
269 // Fill with some pattern
270 uint8_t *p = (uint8_t *)ptr;
273 p += (nBlockSize - 16);
274 for (j = 0; j < 16; j++)
276 p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
280 if (i == pMemArray->nBlockCount - 1)
282 *ptr = NULL; // End of list
286 // Points to the next block
287 *ptr = (void **)(((uint8_t*)ptr) + nBlockSize);
288 ptr += nBlockSize / sizeof(unsigned long);
292 memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
300 //-------------------------------------------------------------------------------------------
301 /** @ingroup group_testmac
303 * @param[in] pMemArray Pointer to WLS Memory management structure
304 * @param[out] ppBlock Pointer where allocated memory block is stored
306 * @return 0 if SUCCESS
309 * This function allocated a memory block from pool
312 //-------------------------------------------------------------------------------------------
313 uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock)
317 if (pMemArray->ppFreeBlock == NULL)
319 printf("wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
323 // FIXME: Remove after debugging
324 if (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage) ||
325 ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))
327 printf("wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
328 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
332 pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
333 *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
335 if ((*pMemArray->ppFreeBlock != NULL) &&
336 (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
337 ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage)))
339 fprintf(stderr, "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
340 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
341 *pMemArray->ppFreeBlock);
345 *ppBlock = (void *) pMemArray->ppFreeBlock;
346 pMemArray->ppFreeBlock = (void **) (*pMemArray->ppFreeBlock);
348 idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
349 if (alloc_track[idx])
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);
357 #ifdef MEMORY_CORRUPTION_DETECT
358 uint32_t nBlockSize = pMemArray->nBlockSize, i;
359 uint8_t *p = (uint8_t *)*ppBlock;
361 p += (nBlockSize - 16);
362 for (i = 0; i < 16; i++)
364 p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
367 alloc_track[idx] = 1;
370 //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
378 //-------------------------------------------------------------------------------------------
379 /** @ingroup group_testmac
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
384 * @return 0 if SUCCESS
387 * This function frees a WLS block of memory and adds it back to the pool
390 //-------------------------------------------------------------------------------------------
391 uint32_t wls_mac_free_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pBlock)
394 unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
396 pBlock = (void *)((unsigned long)pBlock & ~mask);
398 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage))
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);
406 idx = (int)(((uint64_t)pBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
408 if (alloc_track[idx] == 0)
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,
419 #ifdef MEMORY_CORRUPTION_DETECT
420 uint32_t nBlockSize = pMemArray->nBlockSize, i;
421 uint8_t *p = (uint8_t *)pBlock;
423 p += (nBlockSize - 16);
424 for (i = 0; i < 16; i++)
426 if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG)
428 printf("ERROR: Corruption\n");
429 wls_mac_print_stats();
434 alloc_track[idx] = 0;
437 if (((void *) pMemArray->ppFreeBlock) == pBlock)
439 // Simple protection against freeing of already freed block
443 // FIXME: Remove after debugging
444 if ((pMemArray->ppFreeBlock != NULL)
445 && (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage)
446 || ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)))
448 printf("wls_mac_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
449 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
453 // FIXME: Remove after debugging
454 if ((pBlock < pMemArray->pStorage) ||
455 (pBlock >= pMemArray->pEndOfStorage))
457 printf("wls_mac_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
462 *((void **)pBlock) = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
463 pMemArray->ppFreeBlock = (void **) ((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
465 //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
471 //-------------------------------------------------------------------------------------------
472 /** @ingroup group_testmac
476 * @return Pointer to the memory block
479 * This function allocates a block of memory from the pool
482 //-------------------------------------------------------------------------------------------
483 void *wls_mac_alloc_buffer(uint32_t size, uint32_t loc)
486 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
487 PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
489 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
491 if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS)
493 printf("wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
494 wls_mac_print_stats();
499 pWls->nAllocBlocks++;
502 //printf("----------------wls_mac_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
504 //printf("[%p]\n", pBlock);
506 pWls->nTotalAllocCnt++;
507 if (loc < MAX_DL_BUF_LOCATIONS)
508 pWls->nTotalDlBufAllocCnt++;
509 else if (loc < MAX_UL_BUF_LOCATIONS)
510 pWls->nTotalUlBufAllocCnt++;
512 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
519 //-------------------------------------------------------------------------------------------
520 /** @ingroup group_testmac
522 * @param[in] *pMsg Pointer to free
527 * This function frees a block of memory and adds it back to the pool
530 //-------------------------------------------------------------------------------------------
531 void wls_mac_free_buffer(void *pMsg, uint32_t loc)
533 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
534 PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
536 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
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)
541 pWls->nAllocBlocks--;
545 printf("wls_mac_free_buffer Free error\n");
546 wls_mac_print_stats();
550 pWls->nTotalFreeCnt++;
551 if (loc < MAX_DL_BUF_LOCATIONS)
552 pWls->nTotalDlBufFreeCnt++;
553 else if (loc < MAX_UL_BUF_LOCATIONS)
554 pWls->nTotalUlBufFreeCnt++;
556 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
561 //-------------------------------------------------------------------------------------------
562 /** @ingroup group_testmac
566 * @return Number of free blocks
569 * This function queries the number of free blocks in the system
572 //-------------------------------------------------------------------------------------------
573 int wls_mac_num_free_blocks(void)
575 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
577 return (pWls->nTotalBlocks- pWls->nAllocBlocks);
582 void wls_mac_free_list_all(void)
584 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
587 for (idx = 0; idx < TO_FREE_SIZE; idx++)
589 wls_mac_free_list(idx);
592 wls_mac_print_stats();
596 //-------------------------------------------------------------------------------------------
597 /** @ingroup group_testmac
599 * @param[in] pWls Pointer to the WLS_MAC_CTX structure
601 * @return 0 if SUCCESS
604 * This function created a partition and blocks of WLS memory for API exchange between MAC and PHY
607 //-------------------------------------------------------------------------------------------
608 int wls_mac_create_partition(PWLS_MAC_CTX pWls)
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);
619 static volatile int gWlsMacPrintThreadInfo = 0;
621 void wls_mac_print_thread_info(void)
623 gWlsMacPrintThreadInfo = 1;
628 void wls_mac_get_time_stats(uint64_t *pTotal, uint64_t *pUsed, uint32_t nClear)
630 *pTotal = gTotalTick;
640 //-------------------------------------------------------------------------------------------
641 /** @ingroup group_testmac
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
647 * @return New Location in free list array
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.
654 //-------------------------------------------------------------------------------------------
655 int wls_mac_sdu_zbc_block_add_to_free(void* pMsgHeaderHead, int count, uint64_t *pToFreeList)
657 fapi_msg_t *p_fapi_msg = (fapi_msg_t *) pMsgHeaderHead;
659 if (p_fapi_msg->msg_id == FAPI_TX_DATA_REQUEST)
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;
666 if (count < TOTAL_FREE_BLOCKS)
668 pToFreeList[count++] = (uint64_t) p_sdu_elm;
672 printf("wls_mac_sdu_zbc_block_add_to_free: ERROR: Reached max Number of Free Blocks\n");
675 p_sdu_elm = p_sdu_elm->p_next;
683 //-------------------------------------------------------------------------------------------
684 /** @ingroup group_testmac
686 * @param[in] pListElem Pointer to List element header
687 * @param[in] idx Subframe Number
689 * @return Number of blocks freed
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.
696 //-------------------------------------------------------------------------------------------
697 int wls_mac_add_to_free(p_fapi_api_queue_elem_t pListElem, uint32_t idx)
699 p_fapi_api_queue_elem_t pNextMsg = NULL;
701 int count = gToFreeListCnt[idx], nZbcBlocks;
703 pNextMsg = pListElem;
707 if (count < TOTAL_FREE_BLOCKS)
709 gpToFreeList[idx][count] = (uint64_t)pNextMsg;
713 printf("wls_mac_add_to_free: ERROR: Reached max Number of Free Blocks\n");
717 if (pNextMsg->msg_type != FAPI_VENDOR_MSG_HEADER_IND)
719 pMsgHeader = (void *) (pNextMsg + 1);
721 count = wls_mac_sdu_zbc_block_add_to_free(pMsgHeader, count, gpToFreeList[idx]);
724 if (pNextMsg->p_next)
726 pNextMsg = (p_fapi_api_queue_elem_t)(pNextMsg->p_next);
734 gpToFreeList[idx][count] = 0L;
735 gToFreeListCnt[idx] = count;
737 printf("To Free %d\n", count);
743 //-------------------------------------------------------------------------------------------
744 /** @ingroup group_testmac
746 * @param[in] idx subframe Number
748 * @return Number of blocks freed
751 * This function frees all blocks that have been added to the free array
754 //-------------------------------------------------------------------------------------------
755 int wls_mac_free_list(uint32_t idx)
757 p_fapi_api_queue_elem_t pNextMsg = NULL;
760 if(idx >= TO_FREE_SIZE){
761 printf("Error idx %d\n", idx);
765 pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
769 wls_mac_free_buffer(pNextMsg, MIN_DL_BUF_LOCATIONS+0);
770 gpToFreeList[idx][count] = (uint64_t) NULL;
772 if (gpToFreeList[idx][count])
773 pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
778 printf("Free %d\n", count);
779 gToFreeListCnt[idx] = 0;
785 //-------------------------------------------------------------------------------------------
786 /** @ingroup group_testmac
790 * @return 0 if SUCCESS
793 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
797 //-------------------------------------------------------------------------------------------
798 int wls_mac_ready(void)
801 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
802 ret = WLS_Ready(pWls->hWls);
807 //-------------------------------------------------------------------------------------------
808 /** @ingroup group_testmac
812 * @return Number of blocks of APIs received
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.
819 //-------------------------------------------------------------------------------------------
820 int wls_mac_wait(void)
823 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
825 ret = WLS_Wait(pWls->hWls);
830 //-------------------------------------------------------------------------------------------
831 /** @ingroup group_testmac
833 * @param[out] data Location where First API from L1 is stored
835 * @return Size of Message sent from L1
838 * This function queries the APIs sent from L1 to L2 and gets the first pointer to the linked list
841 //-------------------------------------------------------------------------------------------
842 uint32_t wls_mac_recv(uint64_t *data, uint16_t *nFlags)
844 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
845 uint32_t msgSize = 0;
846 uint16_t msgType = 0;
848 *data = WLS_Get(pWls->hWls, &msgSize, &msgType, nFlags);
854 //-------------------------------------------------------------------------------------------
855 /** @ingroup group_testmac
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
862 * @return 0 if SUCCESS
865 * This function adds a block of API from L2 to L1 which will be sent later
868 //-------------------------------------------------------------------------------------------
869 int wls_mac_put(uint64_t pMsg, uint32_t MsgSize, uint16_t MsgTypeID, uint16_t Flags)
872 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
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);
883 //-------------------------------------------------------------------------------------------
884 /** @ingroup group_testmac
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
890 * @return 0 if SUCCESS
893 * This function adds all the ZBC blocks in a TXSDU Message and prepares them to be sent to the L1
896 //-------------------------------------------------------------------------------------------
897 uint32_t wls_mac_send_zbc_blocks(void *pMsgHeaderHead, uint16_t nFlags, int *nZbcBlocks, uint32_t nFlagsUrllc)
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;
905 uint32_t isLast, nPduLen;
906 uint16_t list_flags = nFlags;
907 void *pPayload = NULL;
909 printf("wls_mac_put ZBC blocks: %d\n", nFlags);
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;
917 if (p_list_elm->p_next)
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
925 nFlags = WLS_SG_NEXT; // more blocks in the list
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);
931 printf("Error ZBC block 0x%016lx\n", (uint64_t) pPayload);
934 p_list_elm = p_list_elm->p_next;
942 //-------------------------------------------------------------------------------------------
943 /** @ingroup group_testmac
945 * @param[in] pMsgHeader Pointer to the TxSDuReq Message block
946 * @param[out] nZbcBlocks Number of ZBC blocks
948 * @return 1 if this block is a TxSduReq message. 0 else.
951 * This function checks if a block is a TxSduReq messages and counts the number of ZBC blocks in this
955 //-------------------------------------------------------------------------------------------
956 int wls_mac_is_sdu_zbc_block(void* pMsgHeaderHead, int *nZbcBlocks)
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;
963 if (p_tx_data_req->header.msg_id == FAPI_TX_DATA_REQUEST &&
964 p_list_elm->p_tx_data_elm_list)
974 //-------------------------------------------------------------------------------------------
975 /** @ingroup group_testmac
977 * @param[in] data Pointer to the Linked list header
979 * @return 0 if SUCCESS
982 * This function sends a list of APIs to the L1
985 //-------------------------------------------------------------------------------------------
986 uint32_t wls_mac_send_msg_to_phy(void *data)
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;
995 fapi_msg_t *pMsgHeader;
997 int nZbcBlocks = 0, isZbc = 0, count = 0;
999 printf("wls_mac_send_msg_to_phy\n");
1000 printf("data (0x%lX) sending to phy...\n", (unsigned long)data);
1002 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock);
1006 pListElem = (p_fapi_api_queue_elem_t)data;
1007 wls_mac_add_to_free(pListElem, idx);
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);
1017 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1022 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1027 //-------------------------------------------------------------------------------------------
1028 /** @ingroup group_testmac
1032 * @return Number of blocks added
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
1039 //-------------------------------------------------------------------------------------------
1040 int wls_mac_add_blocks_to_ul(void)
1043 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1045 void *pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+0);
1049 /* allocate blocks for UL transmittion */
1050 while(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
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)))
1057 pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
1064 // free not enqueued block
1067 wls_mac_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS+3);
1075 //-------------------------------------------------------------------------------------------
1076 /** @ingroup group_testmac
1078 * @param[in] data Thread Local Context Structure Pointer
1083 * This is the WLS Receiver thread that is created at Testmac Init and is responsible for receiving
1084 * APIs from L1 to MAC
1087 //-------------------------------------------------------------------------------------------
1088 void *wls_mac_rx_task()
1090 void* buffer_va = 0;
1091 uint64_t buffer_pa = 0;
1092 uint32_t get,i, rc = 0;
1095 uint64_t tWake = 0, tWakePrev = 0, tSleep = 0;
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;
1108 get = wls_mac_wait();
1114 printf("Got %d messages from FAPI Translator\n", get);
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;
1125 if (nFlags != WLS_TF_FIN)
1127 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pElm, i);
1131 pPrev->p_next = pElm;
1135 if ((nFlags & WLS_TF_FIN))
1140 pPrev->p_next = NULL;
1143 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pFirst, i);
1153 wls_mac_add_blocks_to_ul();
1160 void wls_mac_print_recv_list(p_fapi_api_queue_elem_t list, uint32_t i)
1162 printf("\nMAC received response %d from FAPI\n",i);
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)
1167 p_fapi_api_queue_elem_t p_list_elem;
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);
1171 //Fill header for link list of API messages
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;
1184 //-------------------------------------------------------------------------------------------
1185 /** @ingroup group_testmac
1189 * @return 0 if SUCCESS
1192 * This function initialized the WLS threads for the Testmac and allocates memory needed to
1193 * exchange APIs between MAC and PHY
1196 //-------------------------------------------------------------------------------------------
1197 uint32_t wls_mac_init(char * wls_device_name, uint64_t nBlockSize)
1199 uint64_t nWlsMacMemSize;
1200 uint64_t nWlsPhyMemSize;
1201 uint32_t ret = FAILURE;
1202 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1204 static const struct rte_memzone *mng_memzone;
1205 wls_drv_ctx_t *pDrv_ctx;
1209 pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
1210 pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
1212 pWls->nTotalAllocCnt = 0;
1213 pWls->nTotalFreeCnt = 0;
1214 pWls->nTotalUlBufAllocCnt = 0;
1215 pWls->nTotalUlBufFreeCnt = 0;
1216 pWls->nTotalDlBufAllocCnt = 0;
1217 pWls->nTotalDlBufFreeCnt = 0;
1219 pWls->hWls = WLS_Open(wls_device_name, WLS_MASTER_CLIENT, &nWlsMacMemSize, &nWlsPhyMemSize);
1222 /* allocate chuck of memory */
1223 pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nWlsMacMemSize+nWlsPhyMemSize);
1224 if (pWls->pWlsMemBase)
1226 pWls->nTotalMemorySize = nWlsMacMemSize;
1227 // pWls->nBlockSize = wls_mac_check_block_size(nBlockSize);
1229 ret = wls_mac_create_partition(pWls);
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))))
1243 printf("WLS inited ok [%d]\n\n", nBlocks);
1247 printf("can't create WLS Partition");
1254 printf("can't allocate WLS memory");
1260 printf("can't open WLS instance");
1268 //-------------------------------------------------------------------------------------------
1269 /** @ingroup group_testmac
1273 * @return 0 if SUCCESS
1276 * This function destroys the WLS layer for the testmac and de-allocates any memory used
1279 //-------------------------------------------------------------------------------------------
1280 uint32_t wls_mac_destroy(void)
1282 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1284 if (pwls_testmac_thread)
1286 pthread_cancel(*pwls_testmac_thread);
1288 free(pwls_testmac_thread);
1289 pwls_testmac_thread = NULL;
1291 if(pWls->pWlsMemBase)
1293 WLS_Free(pWls->hWls, pWls->pWlsMemBase);
1296 WLS_Close(pWls->hWls);
1297 printf("wls_mac_rx_task: [PID: %6d]... Stopping\n", gwls_pid);
1303 uint8_t mac_dpdk_init()
1309 char *argv[] = {"mac_app", "--proc-type=secondary",
1310 "--file-prefix", "wls", whitelist};
1312 int argc = RTE_DIM(argv);
1314 /* initialize EAL first */
1315 sprintf(whitelist, "-a%s", "0000:00:06.0");
1316 printf("[MAC] Calling rte_eal_init: ");
1318 for (i = 0; i < RTE_DIM(argv); i++)
1320 printf("%s ", argv[i]);
1324 if (rte_eal_init(argc, argv) < 0)
1325 rte_panic("Cannot init EAL\n");