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 WLS_MAC_MEM_SRUCT sWlsStruct;
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;
96 volatile pthread_mutex_t lock;
97 volatile pthread_mutex_t lock_alloc;
98 } WLS_MAC_CTX, *PWLS_MAC_CTX;
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;
109 //-------------------------------------------------------------------------------------------
110 /** @ingroup group_testmac
112 * @param[in] ptr Pointer to display
113 * @param[in] size Size of data
118 * This function displays content of Buffer - Used for debugging
121 //-------------------------------------------------------------------------------------------
122 void wls_mac_show_data(void* ptr, uint32_t size)
127 for(i = 0; i < size; i++)
131 printf("%02x ", d[i]);
138 //-------------------------------------------------------------------------------------------
139 /** @ingroup group_testmac
143 * @return Pointer to WLS_MAC_CTX stucture
146 * This function returns the WLS Local structure which has WLS related parameters
149 //-------------------------------------------------------------------------------------------
150 static PWLS_MAC_CTX wls_mac_get_ctx(void)
152 return &wls_mac_iface;
155 void wls_mac_print_stats(void)
157 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
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));
168 //-------------------------------------------------------------------------------------------
169 /** @ingroup group_testmac
171 * @param[in] ptr Address to convert
173 * @return Converted address
176 * This function converts Virtual Address to Physical Address
179 //-------------------------------------------------------------------------------------------
180 uint64_t wls_mac_va_to_pa(void *ptr)
182 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
183 uint64_t ret = (uint64_t)WLS_VA2PA(pWls->hWls, ptr);
185 //printf("wls_mac_va_to_pa: %p ->%p\n", ptr, (void*)ret);
192 //-------------------------------------------------------------------------------------------
193 /** @ingroup group_testmac
195 * @param[in] ptr Address to convert
197 * @return Converted address
200 * This function converts Physical Address to Virtual Address
203 //-------------------------------------------------------------------------------------------
204 void *wls_mac_pa_to_va(uint64_t ptr)
206 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
207 void *ret = WLS_PA2VA(pWls->hWls, ptr);
209 //printf("wls_mac_pa_to_va: %p -> %p\n", (void*)ptr, ret);
216 //-------------------------------------------------------------------------------------------
217 /** @ingroup group_testmac
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
224 * @return 0 if SUCCESS
227 * This function creates memory blocks from a flat buffer which will be used for communciation
228 * between MAC and PHY
231 //-------------------------------------------------------------------------------------------
232 uint32_t wls_mac_create_mem_array(PWLS_MAC_MEM_SRUCT pMemArray,
233 void *pMemArrayMemory,
234 uint32_t totalSize, uint32_t nBlockSize)
236 int numBlocks = totalSize / nBlockSize;
240 printf("wls_mac_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
241 pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
243 // Can't be less than pointer size
244 if (nBlockSize < sizeof(void *))
249 // Can't be less than one block
250 if (totalSize < sizeof(void *))
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;
261 // Initialize single-linked list of free blocks;
262 ptr = (void **)pMemArrayMemory;
263 for (i = 0; i < pMemArray->nBlockCount; i++)
265 #ifdef MEMORY_CORRUPTION_DETECT
266 // Fill with some pattern
267 uint8_t *p = (uint8_t *)ptr;
270 p += (nBlockSize - 16);
271 for (j = 0; j < 16; j++)
273 p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
277 if (i == pMemArray->nBlockCount - 1)
279 *ptr = NULL; // End of list
283 // Points to the next block
284 *ptr = (void **)(((uint8_t*)ptr) + nBlockSize);
285 ptr += nBlockSize / sizeof(unsigned long);
289 memset(alloc_track, 0, sizeof(uint8_t) * ALLOC_TRACK_SIZE);
297 //-------------------------------------------------------------------------------------------
298 /** @ingroup group_testmac
300 * @param[in] pMemArray Pointer to WLS Memory management structure
301 * @param[out] ppBlock Pointer where allocated memory block is stored
303 * @return 0 if SUCCESS
306 * This function allocated a memory block from pool
309 //-------------------------------------------------------------------------------------------
310 uint32_t wls_mac_alloc_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void **ppBlock)
314 if (pMemArray->ppFreeBlock == NULL)
316 printf("wls_mac_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
320 // FIXME: Remove after debugging
321 if (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage) ||
322 ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))
324 printf("wls_mac_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
325 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
329 pMemArray->ppFreeBlock = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
330 *pMemArray->ppFreeBlock = (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
332 if ((*pMemArray->ppFreeBlock != NULL) &&
333 (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
334 ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage)))
336 fprintf(stderr, "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
337 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
338 *pMemArray->ppFreeBlock);
342 *ppBlock = (void *) pMemArray->ppFreeBlock;
343 pMemArray->ppFreeBlock = (void **) (*pMemArray->ppFreeBlock);
345 idx = (((uint64_t)*ppBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
346 if (alloc_track[idx])
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);
354 #ifdef MEMORY_CORRUPTION_DETECT
355 uint32_t nBlockSize = pMemArray->nBlockSize, i;
356 uint8_t *p = (uint8_t *)*ppBlock;
358 p += (nBlockSize - 16);
359 for (i = 0; i < 16; i++)
361 p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
364 alloc_track[idx] = 1;
367 //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
375 //-------------------------------------------------------------------------------------------
376 /** @ingroup group_testmac
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
381 * @return 0 if SUCCESS
384 * This function frees a WLS block of memory and adds it back to the pool
387 //-------------------------------------------------------------------------------------------
388 uint32_t wls_mac_free_mem_array(PWLS_MAC_MEM_SRUCT pMemArray, void *pBlock)
391 unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
393 pBlock = (void *)((unsigned long)pBlock & ~mask);
395 if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage))
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);
403 idx = (int)(((uint64_t)pBlock - (uint64_t)pMemArray->pStorage)) / pMemArray->nBlockSize;
405 if (alloc_track[idx] == 0)
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,
416 #ifdef MEMORY_CORRUPTION_DETECT
417 uint32_t nBlockSize = pMemArray->nBlockSize, i;
418 uint8_t *p = (uint8_t *)pBlock;
420 p += (nBlockSize - 16);
421 for (i = 0; i < 16; i++)
423 if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG)
425 printf("ERROR: Corruption\n");
426 wls_mac_print_stats();
431 alloc_track[idx] = 0;
434 if (((void *) pMemArray->ppFreeBlock) == pBlock)
436 // Simple protection against freeing of already freed block
440 // FIXME: Remove after debugging
441 if ((pMemArray->ppFreeBlock != NULL)
442 && (((void *) pMemArray->ppFreeBlock < pMemArray->pStorage)
443 || ((void *) pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)))
445 printf("wls_mac_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
446 pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
450 // FIXME: Remove after debugging
451 if ((pBlock < pMemArray->pStorage) ||
452 (pBlock >= pMemArray->pEndOfStorage))
454 printf("wls_mac_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
459 *((void **)pBlock) = (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
460 pMemArray->ppFreeBlock = (void **) ((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
462 //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
468 //-------------------------------------------------------------------------------------------
469 /** @ingroup group_testmac
473 * @return Pointer to the memory block
476 * This function allocates a block of memory from the pool
479 //-------------------------------------------------------------------------------------------
480 void *wls_mac_alloc_buffer(uint32_t size, uint32_t loc)
483 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
484 PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
486 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
488 if (wls_mac_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS)
490 printf("wls_mac_alloc_buffer alloc error size[%d] loc[%d]\n", size, loc);
491 wls_mac_print_stats();
496 pWls->nAllocBlocks++;
499 //printf("----------------wls_mac_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
501 //printf("[%p]\n", pBlock);
503 pWls->nTotalAllocCnt++;
504 if (loc < MAX_DL_BUF_LOCATIONS)
505 pWls->nTotalDlBufAllocCnt++;
506 else if (loc < MAX_UL_BUF_LOCATIONS)
507 pWls->nTotalUlBufAllocCnt++;
509 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
516 //-------------------------------------------------------------------------------------------
517 /** @ingroup group_testmac
519 * @param[in] *pMsg Pointer to free
524 * This function frees a block of memory and adds it back to the pool
527 //-------------------------------------------------------------------------------------------
528 void wls_mac_free_buffer(void *pMsg, uint32_t loc)
530 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
531 PWLS_MAC_MEM_SRUCT pMemArray = &pWls->sWlsStruct;
533 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock_alloc);
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)
538 pWls->nAllocBlocks--;
542 printf("wls_mac_free_buffer Free error\n");
543 wls_mac_print_stats();
547 pWls->nTotalFreeCnt++;
548 if (loc < MAX_DL_BUF_LOCATIONS)
549 pWls->nTotalDlBufFreeCnt++;
550 else if (loc < MAX_UL_BUF_LOCATIONS)
551 pWls->nTotalUlBufFreeCnt++;
553 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock_alloc);
558 //-------------------------------------------------------------------------------------------
559 /** @ingroup group_testmac
563 * @return Number of free blocks
566 * This function queries the number of free blocks in the system
569 //-------------------------------------------------------------------------------------------
570 int wls_mac_num_free_blocks(void)
572 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
574 return (pWls->nTotalBlocks- pWls->nAllocBlocks);
579 void wls_mac_free_list_all(void)
581 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
584 for (idx = 0; idx < TO_FREE_SIZE; idx++)
586 wls_mac_free_list(idx);
589 wls_mac_print_stats();
593 //-------------------------------------------------------------------------------------------
594 /** @ingroup group_testmac
596 * @param[in] pWls Pointer to the WLS_MAC_CTX structure
598 * @return 0 if SUCCESS
601 * This function created a partition and blocks of WLS memory for API exchange between MAC and PHY
604 //-------------------------------------------------------------------------------------------
605 int wls_mac_create_partition(PWLS_MAC_CTX pWls)
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);
616 static volatile int gWlsMacPrintThreadInfo = 0;
618 void wls_mac_print_thread_info(void)
620 gWlsMacPrintThreadInfo = 1;
625 void wls_mac_get_time_stats(uint64_t *pTotal, uint64_t *pUsed, uint32_t nClear)
627 *pTotal = gTotalTick;
637 //-------------------------------------------------------------------------------------------
638 /** @ingroup group_testmac
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
644 * @return New Location in free list array
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.
651 //-------------------------------------------------------------------------------------------
652 int wls_mac_sdu_zbc_block_add_to_free(void* pMsgHeaderHead, int count, uint64_t *pToFreeList)
654 fapi_msg_t *p_fapi_msg = (fapi_msg_t *) pMsgHeaderHead;
656 if (p_fapi_msg->msg_id == FAPI_TX_DATA_REQUEST)
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;
663 if (count < TOTAL_FREE_BLOCKS)
665 pToFreeList[count++] = (uint64_t) p_sdu_elm;
669 printf("wls_mac_sdu_zbc_block_add_to_free: ERROR: Reached max Number of Free Blocks\n");
672 p_sdu_elm = p_sdu_elm->p_next;
680 //-------------------------------------------------------------------------------------------
681 /** @ingroup group_testmac
683 * @param[in] pListElem Pointer to List element header
684 * @param[in] idx Subframe Number
686 * @return Number of blocks freed
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.
693 //-------------------------------------------------------------------------------------------
694 int wls_mac_add_to_free(p_fapi_api_queue_elem_t pListElem, uint32_t idx)
696 p_fapi_api_queue_elem_t pNextMsg = NULL;
698 int count = gToFreeListCnt[idx], nZbcBlocks;
700 pNextMsg = pListElem;
704 if (count < TOTAL_FREE_BLOCKS)
706 gpToFreeList[idx][count] = (uint64_t)pNextMsg;
710 printf("wls_mac_add_to_free: ERROR: Reached max Number of Free Blocks\n");
714 if (pNextMsg->msg_type != FAPI_VENDOR_MSG_HEADER_IND)
716 pMsgHeader = (void *) (pNextMsg + 1);
718 count = wls_mac_sdu_zbc_block_add_to_free(pMsgHeader, count, gpToFreeList[idx]);
721 if (pNextMsg->p_next)
723 pNextMsg = (p_fapi_api_queue_elem_t)(pNextMsg->p_next);
731 gpToFreeList[idx][count] = 0L;
732 gToFreeListCnt[idx] = count;
734 printf("To Free %d\n", count);
740 //-------------------------------------------------------------------------------------------
741 /** @ingroup group_testmac
743 * @param[in] idx subframe Number
745 * @return Number of blocks freed
748 * This function frees all blocks that have been added to the free array
751 //-------------------------------------------------------------------------------------------
752 int wls_mac_free_list(uint32_t idx)
754 p_fapi_api_queue_elem_t pNextMsg = NULL;
757 if(idx >= TO_FREE_SIZE){
758 printf("Error idx %d\n", idx);
762 pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
766 wls_mac_free_buffer(pNextMsg, MIN_DL_BUF_LOCATIONS+0);
767 gpToFreeList[idx][count] = (uint64_t) NULL;
769 if (gpToFreeList[idx][count])
770 pNextMsg = (p_fapi_api_queue_elem_t)gpToFreeList[idx][count];
775 printf("Free %d\n", count);
776 gToFreeListCnt[idx] = 0;
782 //-------------------------------------------------------------------------------------------
783 /** @ingroup group_testmac
787 * @return 0 if SUCCESS
790 * This function is called at WLS init and waits in an infinite for L1 to respond back with some information
794 //-------------------------------------------------------------------------------------------
795 int wls_mac_ready(void)
798 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
799 ret = WLS_Ready(pWls->hWls);
804 //-------------------------------------------------------------------------------------------
805 /** @ingroup group_testmac
809 * @return Number of blocks of APIs received
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.
816 //-------------------------------------------------------------------------------------------
817 int wls_mac_wait(void)
820 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
822 ret = WLS_Wait(pWls->hWls);
827 //-------------------------------------------------------------------------------------------
828 /** @ingroup group_testmac
830 * @param[out] data Location where First API from L1 is stored
832 * @return Size of Message sent from L1
835 * This function queries the APIs sent from L1 to L2 and gets the first pointer to the linked list
838 //-------------------------------------------------------------------------------------------
839 uint32_t wls_mac_recv(uint64_t *data, uint16_t *nFlags)
841 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
842 uint32_t msgSize = 0;
843 uint16_t msgType = 0;
845 *data = WLS_Get(pWls->hWls, &msgSize, &msgType, nFlags);
851 //-------------------------------------------------------------------------------------------
852 /** @ingroup group_testmac
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
859 * @return 0 if SUCCESS
862 * This function adds a block of API from L2 to L1 which will be sent later
865 //-------------------------------------------------------------------------------------------
866 int wls_mac_put(uint64_t pMsg, uint32_t MsgSize, uint16_t MsgTypeID, uint16_t Flags)
869 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
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);
880 //-------------------------------------------------------------------------------------------
881 /** @ingroup group_testmac
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
887 * @return 0 if SUCCESS
890 * This function adds all the ZBC blocks in a TXSDU Message and prepares them to be sent to the L1
893 //-------------------------------------------------------------------------------------------
894 uint32_t wls_mac_send_zbc_blocks(void *pMsgHeaderHead, uint16_t nFlags, int *nZbcBlocks, uint32_t nFlagsUrllc)
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;
902 uint32_t isLast, nPduLen;
903 uint16_t list_flags = nFlags;
904 void *pPayload = NULL;
906 printf("wls_mac_put ZBC blocks: %d\n", nFlags);
910 nPduLen = p_list_elm->msg_len + sizeof(fapi_api_queue_elem_t);
911 pPayload = (void *) p_list_elm;
912 nMsgType = FAPI_VENDOR_MSG_PHY_ZBC_BLOCK_REQ;
914 if (p_list_elm->p_next)
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
922 nFlags = WLS_SG_NEXT; // more blocks in the list
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);
928 printf("Error ZBC block 0x%016lx\n", (uint64_t) pPayload);
931 p_list_elm = p_list_elm->p_next;
939 //-------------------------------------------------------------------------------------------
940 /** @ingroup group_testmac
942 * @param[in] pMsgHeader Pointer to the TxSDuReq Message block
943 * @param[out] nZbcBlocks Number of ZBC blocks
945 * @return 1 if this block is a TxSduReq message. 0 else.
948 * This function checks if a block is a TxSduReq messages and counts the number of ZBC blocks in this
952 //-------------------------------------------------------------------------------------------
953 int wls_mac_is_sdu_zbc_block(void* pMsgHeaderHead, int *nZbcBlocks)
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;
960 if (p_tx_data_req->header.msg_id == FAPI_TX_DATA_REQUEST &&
961 p_list_elm->p_tx_data_elm_list)
971 //-------------------------------------------------------------------------------------------
972 /** @ingroup group_testmac
974 * @param[in] data Pointer to the Linked list header
976 * @return 0 if SUCCESS
979 * This function sends a list of APIs to the L1
982 //-------------------------------------------------------------------------------------------
983 uint32_t wls_mac_send_msg_to_phy(void *data)
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;
992 fapi_msg_t *pMsgHeader;
994 int nZbcBlocks = 0, isZbc = 0, count = 0;
996 printf("wls_mac_send_msg_to_phy\n");
997 printf("data (0x%lX) sending to phy...\n", (unsigned long)data);
999 pthread_mutex_lock((pthread_mutex_t *)&pWls->lock);
1003 pListElem = (p_fapi_api_queue_elem_t)data;
1004 wls_mac_add_to_free(pListElem, idx);
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);
1014 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1019 pthread_mutex_unlock((pthread_mutex_t *)&pWls->lock);
1024 //-------------------------------------------------------------------------------------------
1025 /** @ingroup group_testmac
1029 * @return Number of blocks added
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
1036 //-------------------------------------------------------------------------------------------
1037 int wls_mac_add_blocks_to_ul(void)
1040 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1042 void *pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+0);
1046 /* allocate blocks for UL transmittion */
1047 while(WLS_EnqueueBlock(pWls->hWls,(uint64_t)wls_mac_va_to_pa(pMsg)))
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)))
1054 pMsg = wls_mac_alloc_buffer(0, MIN_UL_BUF_LOCATIONS+1);
1061 // free not enqueued block
1064 wls_mac_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS+3);
1072 //-------------------------------------------------------------------------------------------
1073 /** @ingroup group_testmac
1075 * @param[in] data Thread Local Context Structure Pointer
1080 * This is the WLS Receiver thread that is created at Testmac Init and is responsible for receiving
1081 * APIs from L1 to MAC
1084 //-------------------------------------------------------------------------------------------
1085 void *wls_mac_rx_task()
1087 void* buffer_va = 0;
1088 uint64_t buffer_pa = 0;
1089 uint32_t get,i, rc = 0;
1092 uint64_t tWake = 0, tWakePrev = 0, tSleep = 0;
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;
1105 get = wls_mac_wait();
1111 printf("Got %d messages from FAPI Translator\n", get);
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;
1122 if (nFlags != WLS_TF_FIN)
1124 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pElm, i);
1128 pPrev->p_next = pElm;
1132 if ((nFlags & WLS_TF_FIN))
1137 pPrev->p_next = NULL;
1140 wls_mac_print_recv_list((p_fapi_api_queue_elem_t) pFirst, i);
1150 wls_mac_add_blocks_to_ul();
1157 void wls_mac_print_recv_list(p_fapi_api_queue_elem_t list, uint32_t i)
1159 printf("\nMAC received response %d from FAPI\n",i);
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)
1164 p_fapi_api_queue_elem_t p_list_elem;
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);
1168 //Fill header for link list of API messages
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;
1181 //-------------------------------------------------------------------------------------------
1182 /** @ingroup group_testmac
1186 * @return 0 if SUCCESS
1189 * This function initialized the WLS threads for the Testmac and allocates memory needed to
1190 * exchange APIs between MAC and PHY
1193 //-------------------------------------------------------------------------------------------
1194 uint32_t wls_mac_init(char * wls_device_name, uint64_t nTotalMemorySize)
1196 uint32_t ret = FAILURE;
1197 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1199 static const struct rte_memzone *mng_memzone;
1200 wls_drv_ctx_t *pDrv_ctx;
1204 pthread_mutex_init((pthread_mutex_t *)&pWls->lock, NULL);
1205 pthread_mutex_init((pthread_mutex_t *)&pWls->lock_alloc, NULL);
1207 pWls->nTotalAllocCnt = 0;
1208 pWls->nTotalFreeCnt = 0;
1209 pWls->nTotalUlBufAllocCnt = 0;
1210 pWls->nTotalUlBufFreeCnt = 0;
1211 pWls->nTotalDlBufAllocCnt = 0;
1212 pWls->nTotalDlBufFreeCnt = 0;
1214 pWls->hWls = WLS_Open(wls_device_name, WLS_MASTER_CLIENT, nTotalMemorySize);
1217 /* allocate chuck of memory */
1218 pWls->pWlsMemBase = WLS_Alloc(pWls->hWls, nTotalMemorySize);
1219 if (pWls->pWlsMemBase)
1221 pWls->nTotalMemorySize = (uint32_t) nTotalMemorySize;
1223 ret = wls_mac_create_partition(pWls);
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))))
1237 printf("WLS inited ok [%d]\n\n", nBlocks);
1241 printf("can't create WLS Partition");
1248 printf("can't allocate WLS memory");
1254 printf("can't open WLS instance");
1262 //-------------------------------------------------------------------------------------------
1263 /** @ingroup group_testmac
1267 * @return 0 if SUCCESS
1270 * This function destroys the WLS layer for the testmac and de-allocates any memory used
1273 //-------------------------------------------------------------------------------------------
1274 uint32_t wls_mac_destroy(void)
1276 PWLS_MAC_CTX pWls = wls_mac_get_ctx();
1278 if (pwls_testmac_thread)
1280 pthread_cancel(*pwls_testmac_thread);
1282 free(pwls_testmac_thread);
1283 pwls_testmac_thread = NULL;
1285 if(pWls->pWlsMemBase)
1287 WLS_Free(pWls->hWls, pWls->pWlsMemBase);
1290 WLS_Close(pWls->hWls);
1291 printf("wls_mac_rx_task: [PID: %6d]... Stopping\n", gwls_pid);
1297 uint8_t mac_dpdk_init()
1303 char *argv[] = {"mac_app", "--proc-type=secondary",
1304 "--file-prefix", "wls", whitelist};
1306 int argc = RTE_DIM(argv);
1308 /* initialize EAL first */
1309 sprintf(whitelist, "-w %s", "0000:00:06.0");
1310 printf("[MAC] Calling rte_eal_init: ");
1312 for (i = 0; i < RTE_DIM(argv); i++)
1314 printf("%s ", argv[i]);
1318 if (rte_eal_init(argc, argv) < 0)
1319 rte_panic("Cannot init EAL\n");