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 * @file This file has Shared Memory interface functions between FAPI and PHY
21 * @defgroup nr5g_fapi_source_framework_wls_fapi2phy_group
24 #include "nr5g_fapi_std.h"
25 #include "nr5g_fapi_common_types.h"
26 #include "nr5g_fapi_internal.h"
27 #include "nr5g_fapi_wls.h"
28 #include "nr5g_fapi_fapi2phy_wls.h"
29 #include "nr5g_fapi_log.h"
31 static uint32_t g_to_free_send_list_cnt[TO_FREE_SIZE] = { 0 };
32 static uint64_t g_to_free_send_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} };
33 static uint32_t g_to_free_recv_list_cnt[TO_FREE_SIZE] = { 0 };
34 static uint64_t g_to_free_recv_list[TO_FREE_SIZE][TOTAL_FREE_BLOCKS] = { {0L} };
36 //------------------------------------------------------------------------------
37 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
39 * @param data Pointer to validate
41 * @return TRUE If pointer is within valid shared WLS memory region
42 * FALSE If pointer is out of valid shared WLS memory region
45 * This function validates pointer's in WLS shared memory region
48 //------------------------------------------------------------------------------
49 uint8_t nr5g_fapi_fapi2phy_is_valid_wls_ptr(
52 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
53 if ((unsigned long)data >= (unsigned long)p_wls_ctx->pPartitionMemBase &&
54 (unsigned long)data < ((unsigned long)p_wls_ctx->pPartitionMemBase +
55 p_wls_ctx->nPartitionMemSize)) {
62 //------------------------------------------------------------------------------
63 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
67 * @return A pointer to WLS_HANDLE stucture
70 * This function returns the WLS instance
73 //------------------------------------------------------------------------------
74 static inline WLS_HANDLE nr5g_fapi_fapi2phy_wls_instance(
77 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
78 return p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
81 //----------------------------------------------------------------------------------
82 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
84 * @param[out] data Location where First API from L1 is stored
86 * @return Size of Message sent from L1
89 * This function queries the APIs sent from L1 to L2 and gets the first pointer
93 //----------------------------------------------------------------------------------
94 static inline uint64_t *nr5g_fapi_fapi2phy_wls_get(
99 uint64_t *data = NULL;
102 uint16_t mt = 0, f = 0;
104 h_wls = nr5g_fapi_fapi2phy_wls_instance();
105 data = (uint64_t *) WLS_Get(h_wls, &ms, &mt, &f);
106 *msg_size = ms, *msg_type = mt, *flags = f;
107 NR5G_FAPI_LOG(TRACE_LOG, ("[FAPI2PHY WLS][GET] %p size: %d "
108 "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
113 //----------------------------------------------------------------------------------
114 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
116 * @param[in] p_msg Pointer to API block that needs to be sent to L1
117 * @param[in] msg_size Size of Message
118 * @param[in] msg_id Message Id
119 * @param[in] flags Special flags needed for WLS
121 * @return 0 if SUCCESS
124 * This function adds a block of API from L2 to L1 which will be sent later
127 //----------------------------------------------------------------------------------
128 static inline uint8_t nr5g_fapi_fapi2phy_wls_put(
135 WLS_HANDLE h_phy_wls = nr5g_fapi_fapi2phy_wls_instance();
136 uint64_t pa = nr5g_fapi_wls_va_to_pa(h_phy_wls, (void *)p_msg);
137 NR5G_FAPI_LOG(TRACE_LOG, ("[FAPI2PHY WLS][PUT] %ld size: %d "
138 "type: %x flags: %x", pa, msg_size, msg_type, flags));
139 ret = WLS_Put(h_phy_wls, pa, msg_size, msg_type, flags);
144 //----------------------------------------------------------------------------------
145 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
149 * @return Number of blocks of APIs received
152 * This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
153 * during runtime when L2 sends a API to L1 and then waits for response back.
156 //----------------------------------------------------------------------------------
157 static inline uint8_t nr5g_fapi_fapi2phy_wls_wait(
161 // NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for L1 to respond in WLS Wait"));
162 ret = WLS_Wait(nr5g_fapi_fapi2phy_wls_instance());
166 //------------------------------------------------------------------------------
167 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
169 * @param[out] data Location where First API from L1 is stored
171 * @return Size of Message sent from L1
174 * This function checks if this is the last message in this tti.
177 //------------------------------------------------------------------------------
178 static inline uint8_t is_msg_present(
181 return (!((flags & WLS_TF_FIN) || (flags == 0)));
184 //----------------------------------------------------------------------------------
185 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
187 * @param[out] data Location where First API from L1 is stored
189 * @return Size of Message sent from L1
192 * This function queries the APIs sent from L1 to L2 and gets the first pointer
196 //----------------------------------------------------------------------------------
197 PMAC2PHY_QUEUE_EL nr5g_fapi_fapi2phy_wls_recv(
200 uint16_t msg_type = 0;
202 uint32_t msg_size = 0;
203 uint32_t num_elms = 0;
204 uint64_t *p_msg = NULL;
205 static uint32_t g_free_recv_idx = 0;
206 PMAC2PHY_QUEUE_EL p_qelm_list = NULL;
207 PMAC2PHY_QUEUE_EL p_qelm = NULL;
208 PMAC2PHY_QUEUE_EL p_tail_qelm = NULL;
209 uint64_t start_tick = 0;
211 num_elms = nr5g_fapi_fapi2phy_wls_wait();
215 start_tick = __rdtsc();
218 p_msg = nr5g_fapi_fapi2phy_wls_get(&msg_size, &msg_type, &flags);
220 WLS_HANDLE h_wls = nr5g_fapi_fapi2phy_wls_instance();
221 p_qelm = (PMAC2PHY_QUEUE_EL)
222 nr5g_fapi_wls_pa_to_va(h_wls, (uint64_t) p_msg);
223 if (nr5g_fapi_fapi2phy_is_valid_wls_ptr(p_qelm) == FALSE) {
224 printf("Error: Invalid Ptr\n");
227 p_qelm->pNext = NULL;
229 p_tail_qelm->pNext = p_qelm;
230 p_tail_qelm = p_qelm;
232 p_qelm_list = p_qelm;
233 p_tail_qelm = p_qelm;
237 } while (num_elms && is_msg_present(flags));
240 wls_fapi_add_recv_apis_to_free(p_qelm_list, g_free_recv_idx);
242 if (g_free_recv_idx >= TO_FREE_SIZE) {
245 // Free 10 TTIs Later
246 wls_fapi_free_recv_free_list(g_free_recv_idx);
248 wls_fapi_add_blocks_to_ul();
250 tick_total_wls_get_per_tti_ul += __rdtsc() - start_tick;
255 //------------------------------------------------------------------------------
256 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
258 * @param[in] p_msg_header Pointer to the TxSDuReq Message block
259 * @param[out] n_zbc_blocks Number of ZBC blocks
261 * @return 1 if this block is a TxSduReq message. 0 else.
264 * This function checks if a block is a TxSduReq messages and counts the number
265 * of ZBC blocks in this API
268 //------------------------------------------------------------------------------
269 int nr5g_fapi_fapi2phy_is_sdu_zbc_block(
273 PL1L2MessageHdr p_msg_header = (PL1L2MessageHdr) p_msg;
276 if (p_msg_header->nMessageType == MSG_TYPE_PHY_TX_REQ) {
277 PTXRequestStruct p_dl_sdu_req = (PTXRequestStruct) p_msg_header;
278 PDLPDUDataStruct p_dl_pdu_data = (PDLPDUDataStruct) (p_dl_sdu_req + 1);
280 for (i = 0; i < p_dl_sdu_req->nPDU; i++) {
281 *num_zbc_blocks += (p_dl_pdu_data->nPduLen1 ? 1 : 0);
282 *num_zbc_blocks += (p_dl_pdu_data->nPduLen2 ? 1 : 0);
286 if (*num_zbc_blocks) {
294 //----------------------------------------------------------------------------------
295 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
297 * @param[in] p_msg_header Pointer to the TxSduReq Message block
298 * @param[in] flags Special flags needed for WLS
299 * @param[in] n_zbc_blocks Number of ZBC blocks in list
301 * @return 0 if SUCCESS
304 * This function adds all the ZBC blocks in a TXSDU Message and prepares them to
308 //------------------------------------------------------------------------------
309 uint32_t nr5g_fapi_fapi2phy_send_zbc_blocks(
313 PL1L2MessageHdr p_msg_header = (PL1L2MessageHdr) p_msg;
314 PTXRequestStruct p_dl_sdu_req = (PTXRequestStruct) p_msg_header;
315 PDLPDUDataStruct p_dl_pdu_data = (PDLPDUDataStruct) (p_dl_sdu_req + 1);
316 uint32_t i, j, is_last, is_last1, msg_type;
317 uint16_t list_flags = flags;
319 for (i = 0; i < p_dl_sdu_req->nPDU; i++) {
320 is_last = (i == (p_dl_sdu_req->nPDU - 1));
321 for (j = 0; j < MAX_DL_PER_UE_CODEWORD_NUM; j++) {
327 pdu_len = p_dl_pdu_data->nPduLen1;
328 p_payload = p_dl_pdu_data->pPayload1;
329 msg_type = MSG_PHY_ZBC_BLOCK0_REQ;
331 pdu_len = p_dl_pdu_data->nPduLen2;
332 p_payload = p_dl_pdu_data->pPayload2;
333 msg_type = MSG_PHY_ZBC_BLOCK1_REQ;
337 is_last1 = (((j == 0) && (p_dl_pdu_data->pPayload2 == 0)) ||
338 (j == (MAX_DL_PER_UE_CODEWORD_NUM - 1)));
339 if ((list_flags & WLS_TF_FIN) && is_last && is_last1) {
345 WLS_HANDLE h_phy_wls = nr5g_fapi_fapi2phy_wls_instance();
346 if (WLS_Put(h_phy_wls, (uint64_t) p_payload, pdu_len, msg_type,
348 printf("Error ZBC block 0x%016lx\n", (uint64_t) p_payload);
359 //------------------------------------------------------------------------------
360 /** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
362 * @param[in] A pointer to the phy instance
363 * @param[in] A data Pointer to the Linked list header
365 * @return 0 if SUCCESS
367 * @description This function sends a list of APIs to the L1 via WLS
370 //------------------------------------------------------------------------------
371 uint8_t nr5g_fapi_fapi2phy_wls_send(
374 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
375 PMAC2PHY_QUEUE_EL p_curr_msg = NULL;
376 PL1L2MessageHdr p_msg_header;
378 uint8_t ret = SUCCESS;
379 int n_zbc_blocks = 0, is_zbc = 0, count = 0;
380 static uint32_t g_free_send_idx = 0;
382 p_curr_msg = (PMAC2PHY_QUEUE_EL) data;
383 wls_fapi_add_send_apis_to_free(p_curr_msg, g_free_send_idx);
385 if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2phy_lock_send)) {
386 NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
390 if (p_curr_msg->pNext) {
391 flags = WLS_SG_FIRST;
395 p_msg_header = (PL1L2MessageHdr) (p_curr_msg + 1);
396 if (p_curr_msg->pNext) { // FIRST/NEXT list element
397 if (SUCCESS != nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
398 p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
399 p_msg_header->nMessageType, flags)) {
400 if (pthread_mutex_unlock((pthread_mutex_t *) &
401 p_wls_ctx->fapi2phy_lock_send)) {
402 NR5G_FAPI_LOG(ERROR_LOG,
403 ("unable to unlock send pthread mutex"));
408 if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_msg_header, &n_zbc_blocks)) { // ZBC blocks
409 if (nr5g_fapi_fapi2phy_send_zbc_blocks(p_msg_header,
411 if (pthread_mutex_unlock((pthread_mutex_t *) &
412 p_wls_ctx->fapi2phy_lock_send)) {
413 NR5G_FAPI_LOG(ERROR_LOG,
414 ("unable to unlock send pthread mutex"));
419 p_curr_msg = p_curr_msg->pNext;
420 } else { /* p_curr_msg->Next */
424 if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_msg_header,
429 if (nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
430 p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
431 p_msg_header->nMessageType, flags) != SUCCESS) {
433 if (pthread_mutex_unlock((pthread_mutex_t *) &
434 p_wls_ctx->fapi2phy_lock_send)) {
435 NR5G_FAPI_LOG(ERROR_LOG,
436 ("unable to unlock send pthread mutex"));
441 if (is_zbc) { // ZBC blocks
442 if (nr5g_fapi_fapi2phy_send_zbc_blocks(p_msg_header,
443 WLS_SG_LAST) != SUCCESS) {
445 if (pthread_mutex_unlock((pthread_mutex_t *) &
446 p_wls_ctx->fapi2phy_lock_send)) {
447 NR5G_FAPI_LOG(ERROR_LOG,
448 ("unable to unlock send pthread mutex"));
454 } /* p_curr_msg->Next */
457 } else { // one block
459 if (nr5g_fapi_fapi2phy_is_sdu_zbc_block(p_curr_msg, &n_zbc_blocks)) {
460 printf("Error ZBC block cannot be only one in the list\n");
461 if (pthread_mutex_unlock((pthread_mutex_t *) &
462 p_wls_ctx->fapi2phy_lock_send)) {
463 NR5G_FAPI_LOG(ERROR_LOG,
464 ("unable to unlock send pthread mutex"));
469 if (SUCCESS != nr5g_fapi_fapi2phy_wls_put((uint64_t) p_curr_msg,
470 p_curr_msg->nMessageLen + sizeof(MAC2PHY_QUEUE_EL),
471 p_curr_msg->nMessageType, flags)) {
473 if (pthread_mutex_unlock((pthread_mutex_t *) &
474 p_wls_ctx->fapi2phy_lock_send)) {
475 NR5G_FAPI_LOG(ERROR_LOG,
476 ("unable to unlock send pthread mutex"));
484 if (g_free_send_idx >= TO_FREE_SIZE)
487 // Free 10 TTIs Later
488 wls_fapi_free_send_free_list(g_free_send_idx);
491 if (pthread_mutex_unlock((pthread_mutex_t *) &
492 p_wls_ctx->fapi2phy_lock_send)) {
493 NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
499 //------------------------------------------------------------------------------
500 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
502 * @param[in] pListElem Pointer to List element header
503 * @param[in] idx Subframe Number
505 * @return Number of blocks freed
507 * @description This function Frees all the blocks in a List Element Linked
508 * List coming from L1 by storing them into an array to be
509 * freed at a later point in time.
511 //------------------------------------------------------------------------------
512 uint8_t get_stats_location(
517 case MSG_TYPE_PHY_CONFIG_REQ:
518 loc = MEM_STAT_CONFIG_REQ;
520 case MSG_TYPE_PHY_START_REQ:
521 loc = MEM_STAT_START_REQ;
523 case MSG_TYPE_PHY_STOP_REQ:
524 loc = MEM_STAT_STOP_REQ;
526 case MSG_TYPE_PHY_SHUTDOWN_REQ:
527 loc = MEM_STAT_SHUTDOWN_REQ;
529 case MSG_TYPE_PHY_DL_CONFIG_REQ:
530 loc = MEM_STAT_DL_CONFIG_REQ;
532 case MSG_TYPE_PHY_UL_CONFIG_REQ:
533 loc = MEM_STAT_UL_CONFIG_REQ;
535 case MSG_TYPE_PHY_UL_DCI_REQ:
536 loc = MEM_STAT_UL_DCI_REQ;
538 case MSG_TYPE_PHY_TX_REQ:
539 loc = MEM_STAT_TX_REQ;
541 case MSG_TYPE_PHY_DL_IQ_SAMPLES:
542 loc = MEM_STAT_DL_IQ_SAMPLES;
544 case MSG_TYPE_PHY_UL_IQ_SAMPLES:
545 loc = MEM_STAT_UL_IQ_SAMPLES;
548 loc = MEM_STAT_DEFAULT;
554 //------------------------------------------------------------------------------
555 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
557 * @param[in] pListElem Pointer to List element header
558 * @param[in] idx Subframe Number
560 * @return Number of blocks freed
562 * @description This function Frees all the blocks in a List Element Linked
563 * List coming from L1 by storing them into an array to be
564 * freed at a later point in time.
566 //------------------------------------------------------------------------------
567 void wls_fapi_add_recv_apis_to_free(
568 PMAC2PHY_QUEUE_EL pListElem,
571 PMAC2PHY_QUEUE_EL pNextMsg = NULL;
572 L1L2MessageHdr *p_msg_header = NULL;
573 PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL;
578 p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
579 h_wls = p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
581 count = g_to_free_recv_list_cnt[idx];
582 pNextMsg = pListElem;
584 if (count >= TOTAL_FREE_BLOCKS) {
585 NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
586 "\t\t\t\tlist index: %d list count: %d max list count: %d",
587 __func__, idx, count, TOTAL_FREE_BLOCKS));
591 g_to_free_recv_list[idx][count++] = (uint64_t) pNextMsg;
592 p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
593 if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) {
594 p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header;
595 for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) {
596 ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload;
597 ptr = (uint8_t *) nr5g_fapi_wls_pa_to_va(h_wls, (uint64_t) ptr);
600 g_to_free_recv_list[idx][count++] = (uint64_t) ptr;
604 pNextMsg = pNextMsg->pNext;
607 g_to_free_recv_list[idx][count] = 0L;
608 g_to_free_recv_list_cnt[idx] = count;
610 NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
613 //------------------------------------------------------------------------------
614 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
616 * @param[in] idx subframe Number
618 * @return Number of blocks freed
620 * @description This function frees all blocks that have been added to the
623 //------------------------------------------------------------------------------
624 void wls_fapi_free_recv_free_list(
627 PMAC2PHY_QUEUE_EL pNextMsg = NULL;
630 if (idx >= TO_FREE_SIZE) {
631 NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx));
635 pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
637 wls_fapi_free_buffer(pNextMsg, MIN_UL_BUF_LOCATIONS);
638 g_to_free_recv_list[idx][count++] = 0L;
639 if (g_to_free_recv_list[idx][count])
640 pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
645 NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
646 g_to_free_recv_list_cnt[idx] = 0;
651 //------------------------------------------------------------------------------
652 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
654 * @param[in] pListElem Pointer to List element header
655 * @param[in] idx Subframe Number
657 * @return Number of blocks freed
659 * @description This function Frees all the blocks in a List Element Linked
660 * List coming from L1 by storing them into an array to be
661 * freed at a later point in time.
663 //------------------------------------------------------------------------------
664 void wls_fapi_add_send_apis_to_free(
665 PMAC2PHY_QUEUE_EL pListElem,
668 PMAC2PHY_QUEUE_EL pNextMsg = NULL;
669 L1L2MessageHdr *p_msg_header = NULL;
670 PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL;
674 count = g_to_free_send_list_cnt[idx];
675 pNextMsg = pListElem;
677 if (count >= TOTAL_FREE_BLOCKS) {
678 NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
679 "\t\t\t\tlist index: %d list count: %d max list count: %d",
680 __func__, idx, count, TOTAL_FREE_BLOCKS));
684 g_to_free_send_list[idx][count++] = (uint64_t) pNextMsg;
685 p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
686 if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) {
687 p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header;
688 for (i = 0; i < p_phy_rx_ulsch_ind->nUlsch; i++) {
689 ptr = p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i].pPayload;
691 g_to_free_send_list[idx][count++] = (uint64_t) ptr;
695 pNextMsg = pNextMsg->pNext;
698 g_to_free_send_list[idx][count] = 0L;
699 g_to_free_send_list_cnt[idx] = count;
701 NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
704 //------------------------------------------------------------------------------
705 /** @ingroup nr5g_fapi_source_framework_wls_lib_group
707 * @param[in] idx subframe Number
709 * @return Number of blocks freed
711 * @description This function frees all blocks that have been added to the
714 //------------------------------------------------------------------------------
715 void wls_fapi_free_send_free_list(
718 PMAC2PHY_QUEUE_EL pNextMsg = NULL;
719 L1L2MessageHdr *p_msg_header = NULL;
720 int count = 0, loc = 0;
722 if (idx >= TO_FREE_SIZE) {
723 NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx));
727 pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count];
729 p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
730 loc = get_stats_location(p_msg_header->nMessageType);
731 wls_fapi_free_buffer(pNextMsg, loc);
732 g_to_free_send_list[idx][count++] = 0L;
733 if (g_to_free_send_list[idx][count])
734 pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[idx][count];
739 NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
740 g_to_free_send_list_cnt[idx] = 0;