FAPI TM, WLS_LIB and ODULOW documentation
[o-du/phy.git] / fapi_5g / source / framework / wls / fapi2mac / nr5g_fapi_fapi2mac_wls.c
diff --git a/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c b/fapi_5g/source/framework/wls/fapi2mac/nr5g_fapi_fapi2mac_wls.c
new file mode 100644 (file)
index 0000000..bded93e
--- /dev/null
@@ -0,0 +1,384 @@
+/******************************************************************************
+*
+*   Copyright (c) 2019 Intel.
+*
+*   Licensed under the Apache License, Version 2.0 (the "License");
+*   you may not use this file except in compliance with the License.
+*   You may obtain a copy of the License at
+*
+*       http://www.apache.org/licenses/LICENSE-2.0
+*
+*   Unless required by applicable law or agreed to in writing, software
+*   distributed under the License is distributed on an "AS IS" BASIS,
+*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*   See the License for the specific language governing permissions and
+*   limitations under the License.
+*
+*******************************************************************************/
+
+/**
+ * @file This file has Shared Memory interface functions between FAPI and MAC 
+ *
+ **/
+
+#include "nr5g_fapi_std.h"
+#include "nr5g_fapi_common_types.h"
+#include "nr5g_fapi_wls.h"
+#include "gnb_l1_l2_api.h"
+#include "nr5g_fapi_fapi2mac_wls.h"
+#include "nr5g_fapi_log.h"
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param data Pointer to validate
+ *
+ *  @return  TRUE If pointer is within valid shared WLS memory region
+ *           FALSE If pointer is out of valid shared WLS memory region
+ *
+ *  @description
+ *  This function validates pointer's in WLS shared memory region
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_is_valid_wls_ptr(
+    void *data)
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    if ((unsigned long)data >= (unsigned long)p_wls_ctx->shmem &&
+        (unsigned long)data < ((unsigned long)p_wls_ctx->shmem +
+            p_wls_ctx->nPartitionMemSize)) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param void
+ *
+ *  @return  A pointer to WLS_HANDLE stucture
+ *
+ *  @description
+ *  This function returns the WLS instance
+ *
+**/
+//------------------------------------------------------------------------------
+static inline WLS_HANDLE nr5g_fapi_fapi2mac_wls_instance(
+    )
+{
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+
+    return p_wls_ctx->h_wls[NR5G_FAPI2MAC_WLS_INST];
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param   void
+ *
+ *  @return  Pointer to the memory block
+ *
+ *  @description
+ *  This function allocates a block of memory from the pool
+ *
+**/
+//------------------------------------------------------------------------------
+void *nr5g_fapi_fapi2mac_wls_alloc_buffer(
+    )
+{
+    uint64_t pa_block = 0;
+    void *p_va_block = NULL;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+    WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock alloc pthread mutex"));
+        return NULL;
+    }
+    pa_block = (uint64_t) WLS_DequeueBlock((void *)h_wls);
+    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_alloc)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock alloc pthread mutex"));
+        return NULL;
+    }
+
+    if (!pa_block) {
+        //NR5G_FAPI_LOG(ERROR_LOG, ("nr5g_fapi_fapi2phy_wls_alloc_buffer alloc error\n"));
+        return NULL;
+    }
+    p_va_block = (void *)nr5g_fapi_wls_pa_to_va(h_wls, pa_block);
+    return p_va_block;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param void
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function is called at WLS init and waits in an infinite for L1 to respond back with some information
+ *  needed by the L2
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_ready(
+    )
+{
+    int ret = SUCCESS;
+    ret = WLS_Ready1(nr5g_fapi_fapi2mac_wls_instance());
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param   void
+ *
+ *  @return  Number of blocks of APIs received
+ *
+ *  @description
+ *  This functions waits in a infinite loop for L1 to send a list of APIs to MAC. This is called
+ *  during runtime when L2 sends a API to L1 and then waits for response back.
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_wait(
+    )
+{
+    int ret = SUCCESS;
+//    NR5G_FAPI_LOG(TRACE_LOG, ("Waiting for MAC to respond in WLS Wait"));
+    ret = WLS_Wait1(nr5g_fapi_fapi2mac_wls_instance());
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function checks if this is the last message in this tti.
+ *
+**/
+//------------------------------------------------------------------------------
+static inline uint8_t is_msg_present(
+    uint16_t flags)
+{
+    return (!((flags & WLS_TF_FIN) || (flags == 0)));
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//------------------------------------------------------------------------------
+uint64_t *nr5g_fapi_fapi2mac_wls_get(
+    uint32_t * msg_size,
+    uint16_t * msg_type,
+    uint16_t * flags)
+{
+    uint64_t *data = NULL;
+    WLS_HANDLE h_wls;
+    uint32_t ms = 0;
+    uint16_t mt = 0, f = 0;
+
+    h_wls = nr5g_fapi_fapi2mac_wls_instance();
+    data = (uint64_t *) WLS_Get1(h_wls, &ms, &mt, &f);
+    *msg_size = ms, *msg_type = mt, *flags = f;
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][GET] %p size: %d "
+            "type: %x flags: %x", data, *msg_size, *msg_type, *flags));
+
+    return data;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param[in]   ptr Pointer to the block to send
+ *  @param[in]   size Size of the block to send
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function sends a single block of API from PHY to MAC
+ *
+**/
+//------------------------------------------------------------------------------
+inline uint8_t nr5g_fapi_fapi2mac_wls_put(
+    p_fapi_api_queue_elem_t p_msg,
+    uint32_t msg_size,
+    uint16_t msg_type,
+    uint16_t flags)
+{
+    uint8_t ret = SUCCESS;
+
+    WLS_HANDLE h_mac_wls = nr5g_fapi_fapi2mac_wls_instance();
+    uint64_t pa = nr5g_fapi_wls_va_to_pa(h_mac_wls, (void *)p_msg);
+    NR5G_FAPI_LOG(TRACE_LOG, ("[NR5G_FAPI][FAPI2MAC WLS][PUT] %ld size: %d "
+            "type: %x flags: %x", pa, msg_size, msg_type, flags));
+
+    ret = WLS_Put1(h_mac_wls, (uint64_t) pa, msg_size, msg_type, flags);
+
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2mac_group
+ *
+ *  @param[in]   p_list Pointer to the linked list head
+ *
+ *  @return  0 if SUCCESS
+ *
+ *  @description
+ *  This function sends a linked list of APIs from PHY to MAC.
+ *
+**/
+//------------------------------------------------------------------------------
+uint8_t nr5g_fapi_fapi2mac_wls_send(
+    p_fapi_api_queue_elem_t p_list_elem)
+{
+    uint8_t ret = SUCCESS;
+    p_fapi_api_queue_elem_t p_curr_msg = NULL;
+    fapi_msg_t *p_msg_header = NULL;
+    uint16_t flags = 0;
+    p_nr5g_fapi_wls_context_t p_wls_ctx = nr5g_fapi_wls_context();
+
+    p_curr_msg = p_list_elem;
+
+    if (pthread_mutex_lock((pthread_mutex_t *) & p_wls_ctx->fapi2mac_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to lock send pthread mutex"));
+        return FAILURE;
+    }
+
+    if (p_curr_msg && p_curr_msg->p_next) {
+        flags = WLS_SG_FIRST;
+        if (p_curr_msg->msg_type == FAPI_MSG_HEADER_IND) {
+            if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                    p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                    FAPI_MSG_HEADER_IND, flags)) {
+                printf("Error\n");
+                if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                        fapi2mac_lock_send)) {
+                    NR5G_FAPI_LOG(ERROR_LOG,
+                        ("unable to unlock send pthread mutex"));
+                }
+                return FAILURE;
+            }
+            p_curr_msg = p_curr_msg->p_next;
+            flags = WLS_SG_NEXT;
+        }
+
+        while (p_curr_msg) {
+            // only batch mode
+            p_msg_header = (fapi_msg_t *) (p_curr_msg + 1);
+            if (p_curr_msg->p_next) {   // FIRST/NEXT
+                if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                        p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                        p_msg_header->msg_id, flags)) {
+                    printf("Error\n");
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2mac_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+                p_curr_msg = p_curr_msg->p_next;
+            } else {            // LAST
+                flags = WLS_SG_LAST;
+                if (SUCCESS != nr5g_fapi_fapi2mac_wls_put(p_curr_msg,
+                        p_curr_msg->msg_len + sizeof(fapi_api_queue_elem_t),
+                        p_msg_header->msg_id, flags)) {
+                    printf("Error\n");
+                    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+                            fapi2mac_lock_send)) {
+                        NR5G_FAPI_LOG(ERROR_LOG,
+                            ("unable to unlock send pthread mutex"));
+                    }
+                    return FAILURE;
+                }
+                p_curr_msg = NULL;
+            }
+            flags = WLS_SG_NEXT;
+        }
+    }
+
+    if (pthread_mutex_unlock((pthread_mutex_t *) & p_wls_ctx->
+            fapi2mac_lock_send)) {
+        NR5G_FAPI_LOG(ERROR_LOG, ("unable to unlock send pthread mutex"));
+        return FAILURE;
+    }
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/** @ingroup nr5g_fapi_source_framework_wls_fapi2phy_group
+ *
+ *  @param[out]   data Location where First API from L1 is stored
+ *
+ *  @return  Size of Message sent from L1
+ *
+ *  @description
+ *  This function queries the APIs sent from L1 to L2 and gets the first pointer
+ *  to the linked list
+ *
+**/
+//------------------------------------------------------------------------------
+p_fapi_api_queue_elem_t nr5g_fapi_fapi2mac_wls_recv(
+    )
+{
+    uint16_t msg_type = 0;
+    uint16_t flags = 0;
+    uint32_t msg_size = 0;
+    uint32_t num_elms = 0;
+    uint64_t *p_msg = NULL;
+    p_fapi_api_queue_elem_t p_qelm_list = NULL;
+    p_fapi_api_queue_elem_t p_qelm = NULL;
+    p_fapi_api_queue_elem_t p_tail_qelm = NULL;
+    WLS_HANDLE h_wls = nr5g_fapi_fapi2mac_wls_instance();
+
+    num_elms = nr5g_fapi_fapi2mac_wls_wait();
+    if (!num_elms)
+        return p_qelm_list;
+
+    do {
+        p_msg = nr5g_fapi_fapi2mac_wls_get(&msg_size, &msg_type, &flags);
+        if (p_msg) {
+            p_qelm = (p_fapi_api_queue_elem_t) nr5g_fapi_wls_pa_to_va(h_wls,
+                (uint64_t) p_msg);
+            if (nr5g_fapi_fapi2mac_is_valid_wls_ptr(p_qelm) == FALSE) {
+                printf("Error: Invalid Ptr\n");
+                continue;
+            }
+            p_qelm->p_next = NULL;
+            if (p_qelm_list) {
+                p_tail_qelm = p_qelm_list;
+                while (NULL != p_tail_qelm->p_next) {
+                    p_tail_qelm = p_tail_qelm->p_next;
+                }
+                p_tail_qelm->p_next = p_qelm;
+            } else {
+                p_qelm_list = p_qelm;
+            }
+        }
+        num_elms--;
+    } while (num_elms && is_msg_present(flags));
+
+    return p_qelm_list;
+}