Update to odulow per maintenance bronze
[o-du/phy.git] / fapi_5g / source / framework / wls / lib / nr5g_fapi_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  * @file This file has Shared Memory interface functions between FAPI and PHY
21  * @defgroup nr5g_fapi_source_framework_wls_lib_group
22  **/
23
24 #include "nr5g_fapi_framework.h"
25 #include "nr5g_fapi_internal.h"
26 #include "nr5g_fapi_wls.h"
27 #include "nr5g_fapi_config_loader.h"
28 #include "nr5g_fapi_log.h"
29 #include "nr5g_fapi_memory.h"
30
31 nr5g_fapi_wls_context_t g_wls_ctx;
32
33 static uint8_t alloc_track[ALLOC_TRACK_SIZE];
34
35 //------------------------------------------------------------------------------
36 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
37  *
38  *  @param void
39  *
40  *  @return  A pointer to WLS Context stucture
41  *
42  *  @description
43  *  This function returns the WLS Context structure which has WLS related parameters
44  *
45 **/
46 //------------------------------------------------------------------------------
47 inline p_nr5g_fapi_wls_context_t nr5g_fapi_wls_context(
48     )
49 {
50     return &g_wls_ctx;
51 }
52
53 //----------------------------------------------------------------------------------
54 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
55  *
56  *  @param void
57  *
58  *  @return  0 if SUCCESS
59  *
60  *  @description
61  *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
62  *  needed by the L2
63  *
64 **/
65 //----------------------------------------------------------------------------------
66 inline uint8_t nr5g_fapi_fapi2phy_wls_ready(
67     )
68 {
69     int retval = 0;
70     p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
71
72     retval = WLS_Ready(p_wls->h_wls[NR5G_FAPI2PHY_WLS_INST]);
73
74     return retval;
75 }
76
77 //----------------------------------------------------------------------------------
78 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
79  *
80  *  @param void
81  *
82  *  @return  0 if SUCCESS
83  *
84  *  @description
85  *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
86  *  needed by the L2
87  *
88 **/
89 //----------------------------------------------------------------------------------
90 inline uint8_t nr5g_fapi_fapi2mac_wls_ready(
91     )
92 {
93     int retval = 0;
94     p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
95
96     retval = WLS_Ready1(p_wls->h_wls[NR5G_FAPI2MAC_WLS_INST]);
97
98     return retval;
99 }
100
101 //------------------------------------------------------------------------------
102 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
103  *
104  *  @param[in]   ptr Pointer to display
105  *  @param[in]   size Size of data
106  *
107  *  @return  void
108  *
109  *  @description
110  *  This function displays content of Buffer - Used for debugging
111  *
112 **/
113 //------------------------------------------------------------------------------
114 void nr5g_fapi_wls_show_data(
115     void *ptr,
116     uint32_t size)
117 {
118     uint8_t *d = ptr;
119     int i;
120
121     for (i = 0; i < size; i++) {
122         if (!(i & 0xf))
123             printf("\n");
124         printf("%02x ", d[i]);
125     }
126     printf("\n");
127 }
128
129 //------------------------------------------------------------------------------
130 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
131  *
132  *  @param   N/A
133  *
134  *  @return  N/A
135  *
136  *  @description
137  *  This function prints to the console FAPI stats
138  *
139 **/
140 //------------------------------------------------------------------------------
141 void nr5g_fapi_wls_print_stats(
142     void)
143 {
144     p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
145     printf("          nTotalBlocks[%5d]  nAllocBlocks[%5d]  nFreeBlocks[%5d]\n",
146         pWls->nTotalBlocks, pWls->nAllocBlocks,
147         (pWls->nTotalBlocks - pWls->nAllocBlocks));
148     printf("        nTotalAllocCnt[%5d] nTotalFreeCnt[%5d]         Diff[%5d]\n",
149         pWls->nTotalAllocCnt, pWls->nTotalFreeCnt,
150         (pWls->nTotalAllocCnt - pWls->nTotalFreeCnt));
151     uint32_t nFinalTotalDlBufAllocCnt = 0, nFinalTotalDlBufFreeCnt = 0, idx;
152
153 //#define PRINTF_DEBUG(fmt, args...) //printf(fmt, ## args)
154 #define PRINTF_DEBUG(fmt, args...)
155     PRINTF_DEBUG("\n");
156     PRINTF_DEBUG("\n        nDlBufAllocCnt: \n");
157     for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
158         nFinalTotalDlBufAllocCnt += pWls->nTotalDlBufAllocCnt[idx];
159         PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufAllocCnt[idx]);
160     }
161     PRINTF_DEBUG("\n");
162     PRINTF_DEBUG("\n         nDlBufFreeCnt: \n");
163     for (idx = 0; idx < MEM_STAT_DEFAULT; idx++) {
164         nFinalTotalDlBufFreeCnt += pWls->nTotalDlBufFreeCnt[idx];
165         PRINTF_DEBUG("[%3d:%5d] ", idx, pWls->nTotalDlBufFreeCnt[idx]);
166     }
167     PRINTF_DEBUG("\n\n");
168
169     printf("        nDlBufAllocCnt[%5d] nDlBufFreeCnt[%5d]         Diff[%5d]\n",
170         nFinalTotalDlBufAllocCnt, nFinalTotalDlBufFreeCnt,
171         (nFinalTotalDlBufAllocCnt - nFinalTotalDlBufFreeCnt));
172     printf
173         ("        nUlBufAllocCnt[%5d] nUlBufFreeCnt[%5d]         Diff[%5d]\n\n",
174         pWls->nTotalUlBufAllocCnt, pWls->nTotalUlBufFreeCnt,
175         (pWls->nTotalUlBufAllocCnt - pWls->nTotalUlBufFreeCnt));
176 }
177
178 //------------------------------------------------------------------------------
179 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
180  *
181  *  @param[in]   ptr Address to convert
182  *
183  *  @return  Converted address
184  *
185  *  @description
186  *  This function converts Virtual Address to Physical Address
187  *
188 **/
189 //------------------------------------------------------------------------------
190 uint64_t nr5g_fapi_wls_va_to_pa(
191     WLS_HANDLE h_wls,
192     void *ptr)
193 {
194     return ((uint64_t) WLS_VA2PA(h_wls, ptr));
195 }
196
197 //------------------------------------------------------------------------------
198 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
199  *
200  *  @param[in]   ptr Address to convert
201  *
202  *  @return  Converted address
203  *
204  *  @description
205  *  This function converts Physical Address to Virtual Address
206  *
207 **/
208 //------------------------------------------------------------------------------
209 void *nr5g_fapi_wls_pa_to_va(
210     WLS_HANDLE h_wls,
211     uint64_t ptr)
212 {
213     return ((void *)WLS_PA2VA(h_wls, ptr));
214 }
215
216 //------------------------------------------------------------------------------
217 /** @ingroup nr5g_fapi_source_framework_wls_lib_group 
218  *
219  *  @param   void
220  *
221  *  @return  Number of blocks added
222  *
223  *  @description
224  *  This function add WLS blocks to the L1 Array which will be used by L1 in 
225  *  every TTI to populate and send back APIs to the MAC
226  *
227 **/
228 //------------------------------------------------------------------------------
229 uint8_t wls_fapi_add_blocks_to_ul(
230     void)
231 {
232     int num_blocks = 0;
233     p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
234     WLS_HANDLE h_wls = pWls->h_wls[NR5G_FAPI2PHY_WLS_INST];
235
236     void *pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
237     if (!pMsg) {
238         return num_blocks;
239     }
240
241     /* allocate blocks for UL transmittion */
242     while (WLS_EnqueueBlock(h_wls, nr5g_fapi_wls_va_to_pa(h_wls, pMsg)) > 0) {
243         num_blocks++;
244         pMsg = wls_fapi_alloc_buffer(0, MIN_UL_BUF_LOCATIONS);
245         if (!pMsg)
246             break;
247     }
248
249     // free not enqueued block
250     if (pMsg) {
251         wls_fapi_free_buffer(pMsg, MIN_UL_BUF_LOCATIONS);
252     }
253
254     return num_blocks;
255 }
256
257 //------------------------------------------------------------------------------
258 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
259  *
260  *  @param          A pointer to the phy instance table.
261  *
262  *  @return         0 if SUCCESS
263  *
264  *  @description    This function initializes WLS layer primitives and allocates
265  *                  memory needed to exchange APIs between FAPI and PHY.
266 **/
267 //------------------------------------------------------------------------------
268 uint8_t nr5g_fapi_wls_init(
269     p_nr5g_fapi_cfg_t cfg)
270 {
271     p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
272     const char *dev_name = "wls0";
273
274     if (p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST] &&
275         p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST]) {
276         // NR5G_FAPI_LOG(ERROR_LOG, ("WLS instance already opened!"));
277         return FAILURE;
278     }
279
280     p_wls_ctx->shmem_size = cfg->wls.shmem_size;
281     p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST] =
282         WLS_Open_Dual(dev_name, WLS_SLAVE_CLIENT,
283         cfg->wls.shmem_size, &p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]);
284     if ((NULL == p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST]) &&
285         (NULL == p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST])) {
286         NR5G_FAPI_LOG(ERROR_LOG, ("[NR5G_FAPI_ WLS] WLS Open Dual Failed."));
287         return FAILURE;
288     }
289     // Issue WLS_Alloc() for FAPI2MAC
290     p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST],
291         p_wls_ctx->shmem_size);
292
293     if (NULL == p_wls_ctx->shmem) {
294         printf("Unable to alloc WLS Memory for FAPI2MAC\n");
295         return FAILURE;
296     }
297
298     p_wls_ctx->shmem = WLS_Alloc(p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST],
299         p_wls_ctx->shmem_size);
300     p_wls_ctx->pWlsMemBase = p_wls_ctx->shmem;
301     p_wls_ctx->nTotalMemorySize = p_wls_ctx->shmem_size;
302     if (NULL == p_wls_ctx->shmem) {
303         printf("Unable to alloc WLS Memory\n");
304         return FAILURE;
305     }
306     // Now the L2 is up so let's make sure that the L1 was started first
307     usleep(1000000);
308     // First let's wait for the L1 and L2 to be present
309     while (nr5g_fapi_fapi2phy_wls_ready()) ;
310     NR5G_FAPI_LOG(INFO_LOG, ("L1 is up..."));
311     // Now the L2 is up so let's make sure that the L1 was started first
312     while (nr5g_fapi_fapi2mac_wls_ready()) ;
313     NR5G_FAPI_LOG(INFO_LOG, ("L2 is up..."));
314
315     // Now that the L2 is up and has completed the Common Memory initialization
316     usleep(1000000);
317     if (FAILURE == nr5g_fapi_wls_memory_init()) {
318         return FAILURE;
319     }
320
321     pthread_mutex_init((pthread_mutex_t *)
322         & p_wls_ctx->fapi2phy_lock_send, NULL);
323     pthread_mutex_init((pthread_mutex_t *)
324         & p_wls_ctx->fapi2phy_lock_alloc, NULL);
325     pthread_mutex_init((pthread_mutex_t *)
326         & p_wls_ctx->fapi2mac_lock_send, NULL);
327     pthread_mutex_init((pthread_mutex_t *)
328         & p_wls_ctx->fapi2mac_lock_alloc, NULL);
329     return SUCCESS;
330 }
331
332 //-------------------------------------------------------------------------------------------
333 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
334  *
335  *  @param[in]   pMemArray Pointer to WLS Memory Management Structure
336  *  @param[in]   pMemArrayMmeory pointer to flat buffer that was allocated
337  *  @param[in]   totalSize total size of flat buffer allocated
338  *  @param[in]   nBlockSize Size of each block that needs to be partitoned by the memory manager
339  *
340  *  @return  0 if SUCCESS
341  *
342  *  @description
343  *  This function creates memory blocks from a flat buffer which will be used for communication between FAPI and PHY
344  *
345 **/
346 //-------------------------------------------------------------------------------------------
347 uint32_t wls_fapi_create_mem_array(
348     PWLS_FAPI_MEM_STRUCT pMemArray,
349     void *pMemArrayMemory,
350     uint32_t totalSize,
351     uint32_t nBlockSize)
352 {
353
354     int numBlocks = totalSize / nBlockSize;
355     void **ptr;
356     uint32_t i;
357
358     printf
359         ("wls_fapi_create_mem_array: pMemArray[%p] pMemArrayMemory[%p] totalSize[%d] nBlockSize[%d] numBlocks[%d]\n",
360         pMemArray, pMemArrayMemory, totalSize, nBlockSize, numBlocks);
361
362     // Can't be less than pointer size
363     if (nBlockSize < sizeof(void *)) {
364         return FAILURE;
365     }
366     // Can't be less than one block
367     if (totalSize < sizeof(void *)) {
368         return FAILURE;
369     }
370
371     pMemArray->ppFreeBlock = (void **)pMemArrayMemory;
372     pMemArray->pStorage = pMemArrayMemory;
373     pMemArray->pEndOfStorage =
374         ((unsigned long *)pMemArrayMemory) +
375         numBlocks * nBlockSize / sizeof(unsigned long);
376     pMemArray->nBlockSize = nBlockSize;
377     pMemArray->nBlockCount = numBlocks;
378
379     // Initialize single-linked list of free blocks;
380     ptr = (void **)pMemArrayMemory;
381     for (i = 0; i < pMemArray->nBlockCount; i++) {
382 #ifdef MEMORY_CORRUPTION_DETECT
383         // Fill with some pattern
384         uint8_t *p = (uint8_t *) ptr;
385         uint32_t j;
386
387         p += (nBlockSize - 16);
388         for (j = 0; j < 16; j++) {
389             p[j] = MEMORY_CORRUPTION_DETECT_FLAG;
390         }
391 #endif
392
393         if (i == pMemArray->nBlockCount - 1) {
394             *ptr = NULL;        // End of list
395         } else {
396             // Points to the next block
397             *ptr = (void **)(((uint8_t *) ptr) + nBlockSize);
398             ptr += nBlockSize / sizeof(unsigned long);
399         }
400     }
401
402     NR5G_FAPI_MEMSET(alloc_track, sizeof(uint8_t) * ALLOC_TRACK_SIZE, 0,
403         sizeof(uint8_t) * ALLOC_TRACK_SIZE);
404
405     return SUCCESS;
406 }
407
408 //-------------------------------------------------------------------------------------------
409 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
410  *
411  *  @param[in]   pWls Pointer to the nr5g_fapi_wls_ctx structure
412  *
413  *  @return  0 if SUCCESS
414  *
415  *  @description
416  *  This function created a partition and blocks of WLS memory for API exchange between FAPI and PHY
417  *
418 **/
419 //-------------------------------------------------------------------------------------------
420 uint8_t wls_fapi_create_partition(
421     p_nr5g_fapi_wls_context_t pWls)
422 {
423 #define WLS_HUGE_DEF_PAGE_SIZEA    0x40000000LL
424     static long hugePageSize = WLS_HUGE_DEF_PAGE_SIZEA;
425     //   NR5G_FAPI_MEMSET(pWls->pWlsMemBase , 0xCC, pWls->nTotalMemorySize);  // This is done by the Master Only
426     pWls->pPartitionMemBase =
427         (void *)(((uint8_t *) pWls->pWlsMemBase) + hugePageSize);
428     pWls->nPartitionMemSize = (pWls->nTotalMemorySize - hugePageSize);
429
430     pWls->nTotalBlocks = pWls->nPartitionMemSize / MSG_MAXSIZE;
431     return wls_fapi_create_mem_array(&pWls->sWlsStruct, pWls->pPartitionMemBase,
432         pWls->nPartitionMemSize, MSG_MAXSIZE);
433 }
434
435 //------------------------------------------------------------------------------
436 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
437  *
438  *  @param[in]      A pointer to the FAPI Memory Structure (Initialized by L2)
439  *  @param[out]     ppBlock Pointer where the allocated memory block is stored     
440  *
441  *  @return         0 if SUCCESS
442  *
443  *  @description    This function allocates a memory block from the pool
444  *
445 **/
446 //------------------------------------------------------------------------------
447 uint32_t wls_fapi_alloc_mem_array(
448     PWLS_FAPI_MEM_STRUCT pMemArray,
449     void **ppBlock)
450 {
451     int idx;
452
453     if (pMemArray->ppFreeBlock == NULL) {
454         printf("wls_fapi_alloc_mem_array pMemArray->ppFreeBlock = NULL\n");
455         return FAILURE;
456     }
457     // FIXME: Remove after debugging
458     if (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage) ||
459         ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage)) {
460         printf
461             ("wls_fapi_alloc_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
462             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
463         return FAILURE;
464     }
465
466     pMemArray->ppFreeBlock =
467         (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
468     *pMemArray->ppFreeBlock =
469         (void **)((unsigned long)*pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
470
471     if ((*pMemArray->ppFreeBlock != NULL) &&
472         (((*pMemArray->ppFreeBlock) < pMemArray->pStorage) ||
473             ((*pMemArray->ppFreeBlock) >= pMemArray->pEndOfStorage))) {
474         fprintf(stderr,
475             "ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
476             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
477             *pMemArray->ppFreeBlock);
478         return FAILURE;
479     }
480
481     *ppBlock = (void *)pMemArray->ppFreeBlock;
482     pMemArray->ppFreeBlock = (void **)(*pMemArray->ppFreeBlock);
483
484     idx =
485         (((uint64_t) * ppBlock -
486             (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
487     if (alloc_track[idx]) {
488         printf
489             ("wls_fapi_alloc_mem_array Double alloc Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
490             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock,
491             *pMemArray->ppFreeBlock);
492         return FAILURE;
493     } else {
494 #ifdef MEMORY_CORRUPTION_DETECT
495         uint32_t nBlockSize = pMemArray->nBlockSize, i;
496         uint8_t *p = (uint8_t *) * ppBlock;
497
498         p += (nBlockSize - 16);
499         for (i = 0; i < 16; i++) {
500             p[i] = MEMORY_CORRUPTION_DETECT_FLAG;
501         }
502 #endif
503         alloc_track[idx] = 1;
504     }
505
506     //printf("Block allocd [%p,%p]\n", pMemArray, *ppBlock);
507
508     return SUCCESS;
509 }
510
511 //------------------------------------------------------------------------------
512 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
513  *
514  *  @param[in]      A pointer to the FAPI Memory Structure (Initialized by L2)
515  *  @param[in]      pBlock Pointer where the allocated memory block is stored     
516  *
517  *  @return         0 if SUCCESS
518  *
519  *  @description    This function frees a WLS block of memory and adds 
520  *                  it back to the pool
521  *
522 **/
523 //------------------------------------------------------------------------------
524 uint32_t wls_fapi_free_mem_array(
525     PWLS_FAPI_MEM_STRUCT pMemArray,
526     void *pBlock)
527 {
528     int idx;
529     unsigned long mask = (((unsigned long)pMemArray->nBlockSize) - 1);
530
531     pBlock = (void *)((unsigned long)pBlock & ~mask);
532
533     if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
534         printf
535             ("wls_fapi_free_mem_array WARNING: Trying to free foreign block;Arr=%p,Blk=%p pStorage [%p .. %p]\n",
536             pMemArray, pBlock, pMemArray->pStorage, pMemArray->pEndOfStorage);
537         return FAILURE;
538     }
539
540     idx =
541         (int)(((uint64_t) pBlock -
542             (uint64_t) pMemArray->pStorage)) / pMemArray->nBlockSize;
543
544     if (alloc_track[idx] == 0) {
545         printf
546             ("wls_fapi_free_mem_array ERROR: Double free Arr=%p,Stor=%p,Free=%p,Curr=%p\n",
547             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock, pBlock);
548         return SUCCESS;
549     } else {
550 #ifdef MEMORY_CORRUPTION_DETECT
551         uint32_t nBlockSize = pMemArray->nBlockSize, i;
552         uint8_t *p = (uint8_t *) pBlock;
553
554         p += (nBlockSize - 16);
555         for (i = 0; i < 16; i++) {
556             if (p[i] != MEMORY_CORRUPTION_DETECT_FLAG) {
557                 printf("ERROR: Corruption\n");
558                 nr5g_fapi_wls_print_stats();
559                 exit(-1);
560             }
561         }
562 #endif
563         alloc_track[idx] = 0;
564     }
565
566     if (((void *)pMemArray->ppFreeBlock) == pBlock) {
567         // Simple protection against freeing of already freed block
568         return SUCCESS;
569     }
570     // FIXME: Remove after debugging
571     if ((pMemArray->ppFreeBlock != NULL)
572         && (((void *)pMemArray->ppFreeBlock < pMemArray->pStorage)
573             || ((void *)pMemArray->ppFreeBlock >= pMemArray->pEndOfStorage))) {
574         printf
575             ("wls_fapi_free_mem_array ERROR: Corrupted MemArray;Arr=%p,Stor=%p,Free=%p\n",
576             pMemArray, pMemArray->pStorage, pMemArray->ppFreeBlock);
577         return FAILURE;
578     }
579     // FIXME: Remove after debugging
580     if ((pBlock < pMemArray->pStorage) || (pBlock >= pMemArray->pEndOfStorage)) {
581         printf("wls_fapi_free_mem_array ERROR: Invalid block;Arr=%p,Blk=%p\n",
582             pMemArray, pBlock);
583         return FAILURE;
584     }
585
586     *((void **)pBlock) =
587         (void **)((unsigned long)pMemArray->ppFreeBlock & 0xFFFFFFFFFFFFFFF0);
588     pMemArray->ppFreeBlock =
589         (void **)((unsigned long)pBlock & 0xFFFFFFFFFFFFFFF0);
590
591     //printf("Block freed [%p,%p]\n", pMemArray, pBlock);
592
593     return SUCCESS;
594 }
595
596 //------------------------------------------------------------------------------
597 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
598  *
599  *  @param          size (if 0 fixed size from pool)
600  *  @param          Number of locations
601  *
602  *  @return         0 if SUCCESS
603  *
604  *  @description    This function initializes WLS layer primitives and allocates
605  *                  memory needed to exchange APIs between FAPI and PHY.
606 **/
607 //------------------------------------------------------------------------------
608 void *wls_fapi_alloc_buffer(
609     uint32_t size,
610     uint32_t loc)
611 {
612     void *pBlock = NULL;
613     p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
614
615     if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
616         NR5G_FAPI_LOG(ERROR_LOG, ("unable to get lock alloc pthread mutex"));
617         exit(-1);
618     }
619
620     if (wls_fapi_alloc_mem_array(&pWls->sWlsStruct, &pBlock) != SUCCESS) {
621         printf("wls_fapi_alloc_buffer alloc error size[%d] loc[%d]\n", size,
622             loc);
623         nr5g_fapi_wls_print_stats();
624         exit(-1);
625     } else {
626         pWls->nAllocBlocks++;
627     }
628
629     //printf("----------------wls_fapi_alloc_buffer: size[%d] loc[%d] buf[%p] nAllocBlocks[%d]\n", size, loc, pBlock, pWls->nAllocBlocks);
630
631     //printf("[%p]\n", pBlock);
632
633     pWls->nTotalAllocCnt++;
634     if (loc < MAX_DL_BUF_LOCATIONS)
635         pWls->nTotalDlBufAllocCnt[loc]++;
636     else if (loc < MAX_UL_BUF_LOCATIONS)
637         pWls->nTotalUlBufAllocCnt++;
638
639     if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
640         NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
641         exit(-1);
642     }
643
644     return pBlock;
645 }
646
647 //------------------------------------------------------------------------------
648 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
649  *
650  *  @param[in]      *pMsg Pointer to free
651  *
652  *  @return         void
653  *
654  *  @descriptioni   This function frees a block of memory and adds it back to 
655  *                  the pool.
656  *
657 **/
658 //------------------------------------------------------------------------------
659 void wls_fapi_free_buffer(
660     void *pMsg,
661     uint32_t loc)
662 {
663     p_nr5g_fapi_wls_context_t pWls = nr5g_fapi_wls_context();
664
665     if (pthread_mutex_lock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
666         NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
667         exit(-1);
668     }
669     //printf("----------------wls_fapi_free_buffer: buf[%p] loc[%d]\n", pMsg, loc);
670     if (wls_fapi_free_mem_array(&pWls->sWlsStruct, (void *)pMsg) == SUCCESS) {
671         pWls->nAllocBlocks--;
672     } else {
673         printf("wls_fapi_free_buffer Free error\n");
674         nr5g_fapi_wls_print_stats();
675         exit(-1);
676     }
677
678     pWls->nTotalFreeCnt++;
679     if (loc < MAX_DL_BUF_LOCATIONS)
680         pWls->nTotalDlBufFreeCnt[loc]++;
681     else if (loc < MAX_UL_BUF_LOCATIONS)
682         pWls->nTotalUlBufFreeCnt++;
683
684     if (pthread_mutex_unlock((pthread_mutex_t *) & pWls->fapi2phy_lock_alloc)) {
685         NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
686         exit(-1);
687     }
688 }
689
690 //------------------------------------------------------------------------------
691 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
692  *
693  *  @param          A pointer to a wls instance
694  *
695  *  @return         0 if SUCCESS
696  *
697  *  @description    This function initializes the WLS layer FAPI2PHY interface 
698  *                  primitives and allocates memory needed to exchange APIs 
699  *                  between FAPI and PHY.
700 **/
701 //------------------------------------------------------------------------------
702 uint8_t nr5g_fapi_wls_memory_init(
703     )
704 {
705     int nBlocks = 0;
706     p_nr5g_fapi_wls_context_t p_wls = nr5g_fapi_wls_context();
707
708     if (FAILURE == wls_fapi_create_partition(p_wls))
709         return FAILURE;
710
711     if ((nBlocks = wls_fapi_add_blocks_to_ul()) == 0) {
712         NR5G_FAPI_LOG(ERROR_LOG, ("Unable to allocate blocks to PHY"));
713         return FAILURE;
714     }
715
716     return SUCCESS;
717 }