+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] pListElem Pointer to List element header
+ * @param[in] idx Subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function Frees all the blocks in a List Element Linked
+ * List coming from L1 by storing them into an array to be
+ * freed at a later point in time.
+**/
+//------------------------------------------------------------------------------
+uint8_t get_stats_location(
+ uint8_t msg_type)
+{
+ uint8_t loc;
+ switch (msg_type) {
+ case MSG_TYPE_PHY_CONFIG_REQ:
+ loc = MEM_STAT_CONFIG_REQ;
+ break;
+ case MSG_TYPE_PHY_START_REQ:
+ loc = MEM_STAT_START_REQ;
+ break;
+ case MSG_TYPE_PHY_STOP_REQ:
+ loc = MEM_STAT_STOP_REQ;
+ break;
+ case MSG_TYPE_PHY_SHUTDOWN_REQ:
+ loc = MEM_STAT_SHUTDOWN_REQ;
+ break;
+ case MSG_TYPE_PHY_DL_CONFIG_REQ:
+ loc = MEM_STAT_DL_CONFIG_REQ;
+ break;
+ case MSG_TYPE_PHY_UL_CONFIG_REQ:
+ loc = MEM_STAT_UL_CONFIG_REQ;
+ break;
+ case MSG_TYPE_PHY_UL_DCI_REQ:
+ loc = MEM_STAT_UL_DCI_REQ;
+ break;
+ case MSG_TYPE_PHY_TX_REQ:
+ loc = MEM_STAT_TX_REQ;
+ break;
+ case MSG_TYPE_PHY_DL_IQ_SAMPLES:
+ loc = MEM_STAT_DL_IQ_SAMPLES;
+ break;
+ case MSG_TYPE_PHY_UL_IQ_SAMPLES:
+ loc = MEM_STAT_UL_IQ_SAMPLES;
+ break;
+ default:
+ loc = MEM_STAT_DEFAULT;
+ }
+
+ return loc;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] pListElem Pointer to List element header
+ * @param[in] idx Subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function Frees all the blocks in a List Element Linked
+ * List coming from L1 by storing them into an array to be
+ * freed at a later point in time.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_add_recv_apis_to_free(
+ PMAC2PHY_QUEUE_EL pListElem,
+ uint32_t idx)
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ L1L2MessageHdr *p_msg_header = NULL;
+ PRXULSCHIndicationStruct p_phy_rx_ulsch_ind = NULL;
+ PULSCHPDUDataStruct p_ulsch_pdu = NULL;
+ uint8_t *ptr = NULL;
+ uint32_t count;
+ uint8_t i;
+
+ WLS_HANDLE h_wls;
+ p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+ h_wls = p_wls_ctx->h_wls[NR5G_FAPI2PHY_WLS_INST];
+
+ count = g_to_free_recv_list_cnt[idx];
+ pNextMsg = pListElem;
+ while (pNextMsg) {
+ if (count >= TOTAL_FREE_BLOCKS) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
+ "\t\t\t\tlist index: %d list count: %d max list count: %d",
+ __func__, idx, count, TOTAL_FREE_BLOCKS));
+ return;
+ }
+
+ g_to_free_recv_list[idx][count++] = (uint64_t) pNextMsg;
+ p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+ if (p_msg_header->nMessageType == MSG_TYPE_PHY_RX_ULSCH_IND) {
+ p_phy_rx_ulsch_ind = (PRXULSCHIndicationStruct) p_msg_header;
+ for (i = 0u; i < p_phy_rx_ulsch_ind->nUlsch; i++) {
+ p_ulsch_pdu = &(p_phy_rx_ulsch_ind->sULSCHPDUDataStruct[i]);
+ if(p_ulsch_pdu->nPduLen > 0) {
+ ptr = (uint8_t *) nr5g_fapi_wls_pa_to_va(h_wls,
+ (uint64_t) p_ulsch_pdu->pPayload);
+
+ if (ptr) {
+ g_to_free_recv_list[idx][count++] = (uint64_t) ptr;
+ }
+ } else {
+ NR5G_FAPI_LOG(DEBUG_LOG, ("%s: Payload for"
+ "MSG_TYPE_PHY_RX_ULSCH_IND ulsch pdu (%u/%u) is NULL."
+ "Skip adding to free list.",
+ __func__, i, p_phy_rx_ulsch_ind->nUlsch));
+ }
+ }
+ }
+ pNextMsg = pNextMsg->pNext;
+ }
+
+ g_to_free_recv_list[idx][count] = 0L;
+ g_to_free_recv_list_cnt[idx] = count;
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] idx subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function frees all blocks that have been added to the
+ * free array
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_recv_free_list(
+ uint32_t idx)
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ int count = 0;
+
+ if (idx >= TO_FREE_SIZE) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, idx));
+ return;
+ }
+
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
+ while (pNextMsg) {
+ wls_fapi_free_buffer(pNextMsg, MIN_UL_BUF_LOCATIONS);
+ g_to_free_recv_list[idx][count++] = 0L;
+ if (g_to_free_recv_list[idx][count])
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_recv_list[idx][count];
+ else
+ pNextMsg = 0L;
+ }
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
+ g_to_free_recv_list_cnt[idx] = 0;
+
+ return;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] pListElem Pointer to List element header
+ * @param[in] idx Subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function Frees all the blocks in a List Element Linked
+ * List coming from L1 by storing them into an array to be
+ * freed at a later point in time.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_add_send_apis_to_free(
+ PMAC2PHY_QUEUE_EL pListElem,
+ uint32_t idx)
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ uint32_t count;
+
+ count = g_to_free_send_list_cnt[idx];
+ pNextMsg = pListElem;
+ while (pNextMsg) {
+ if (count >= TOTAL_FREE_BLOCKS) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
+ "\t\t\t\tlist index: %d list count: %d max list count: %d",
+ __func__, idx, count, TOTAL_FREE_BLOCKS));
+ return;
+ }
+
+ g_to_free_send_list[idx][count++] = (uint64_t) pNextMsg;
+ pNextMsg = pNextMsg->pNext;
+ }
+
+ g_to_free_send_list[idx][count] = 0L;
+ g_to_free_send_list_cnt[idx] = count;
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] idx subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function frees all blocks that have been added to the
+ * free array
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_send_free_list()
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ L1L2MessageHdr *p_msg_header = NULL;
+ int count = 0, loc = 0;
+
+ if (g_free_send_idx >= TO_FREE_SIZE) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, g_free_send_idx));
+ return;
+ }
+
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[g_free_send_idx][count];
+ while (pNextMsg) {
+ p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+ loc = get_stats_location(p_msg_header->nMessageType);
+ wls_fapi_free_buffer(pNextMsg, loc);
+ g_to_free_send_list[g_free_send_idx][count++] = 0L;
+ if (g_to_free_send_list[g_free_send_idx][count])
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list[g_free_send_idx][count];
+ else
+ pNextMsg = 0L;
+ }
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
+ g_to_free_send_list_cnt[g_free_send_idx] = 0;
+
+ return;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] pListElem Pointer to List element header
+ * @param[in] idx Subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function Frees all the blocks in a List Element Linked
+ * List coming from L1 by storing them into an array to be
+ * freed at a later point in time. Used by urllc thread.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_add_send_apis_to_free_urllc(
+ PMAC2PHY_QUEUE_EL pListElem,
+ uint32_t idx)
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ uint32_t count;
+
+ count = g_to_free_send_list_cnt_urllc[idx];
+ pNextMsg = pListElem;
+ while (pNextMsg) {
+ if (count >= TOTAL_FREE_BLOCKS) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: Reached max capacity of free list.\n"
+ "\t\t\t\tlist index: %d list count: %d max list count: %d",
+ __func__, idx, count, TOTAL_FREE_BLOCKS));
+ return;
+ }
+
+ g_to_free_send_list_urllc[idx][count++] = (uint64_t) pNextMsg;
+ pNextMsg = pNextMsg->pNext;
+ }
+
+ g_to_free_send_list_urllc[idx][count] = 0L;
+ g_to_free_send_list_cnt_urllc[idx] = count;
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("To Free %d\n", count));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_lib_group
+ *
+ * @param[in] idx subframe Number
+ *
+ * @return Number of blocks freed
+ *
+ * @description This function frees all blocks that have been added to the
+ * free array. Used by urllc thread.
+**/
+//------------------------------------------------------------------------------
+void wls_fapi_free_send_free_list_urllc()
+{
+ PMAC2PHY_QUEUE_EL pNextMsg = NULL;
+ L1L2MessageHdr *p_msg_header = NULL;
+ int count = 0, loc = 0;
+
+ if (g_free_send_idx_urllc >= TO_FREE_SIZE_URLLC) {
+ NR5G_FAPI_LOG(ERROR_LOG, ("%s: list index: %d\n", __func__, g_free_send_idx_urllc));
+ return;
+ }
+
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list_urllc[g_free_send_idx_urllc][count];
+ while (pNextMsg) {
+ p_msg_header = (PL1L2MessageHdr) (pNextMsg + 1);
+ loc = get_stats_location(p_msg_header->nMessageType);
+ wls_fapi_free_buffer(pNextMsg, loc);
+ g_to_free_send_list_urllc[g_free_send_idx_urllc][count++] = 0L;
+ if (g_to_free_send_list_urllc[g_free_send_idx_urllc][count])
+ pNextMsg = (PMAC2PHY_QUEUE_EL) g_to_free_send_list_urllc[g_free_send_idx_urllc][count];
+ else
+ pNextMsg = 0L;
+ }
+
+ NR5G_FAPI_LOG(DEBUG_LOG, ("Free %d\n", count));
+ g_to_free_send_list_cnt_urllc[g_free_send_idx_urllc] = 0;
+
+ return;
+}