| /* Copyright (c) 2015, The Linux Foundation. All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are |
| met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the following |
| disclaimer in the documentation and/or other materials provided |
| with the distribution. |
| * Neither the name of The Linux Foundation nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| /*=========================================================================== |
| INCLUDE FILES |
| ===========================================================================*/ |
| #include <glink_internal.h> |
| |
| #ifdef FEATURE_TRACER_PACKET |
| #include "glink_tracer.h" |
| #endif |
| /*=========================================================================== |
| MACRO DEFINITION |
| ===========================================================================*/ |
| /*=========================================================================== |
| GLOBAL DATA DECLARATIONS |
| ===========================================================================*/ |
| static os_cs_type glink_transport_q_cs[GLINK_NUM_HOSTS]; |
| |
| #if defined(GLINK_OS_DEFINED_LOGGING) || defined(GLINK_MEMORY_LOGGING) |
| /* glink_log_filter_status indicates if channel filtering is enabled or not */ |
| glink_logging_filter_cfg_type log_filter_cfg = { |
| FALSE, /* Filter Disabled */ |
| "", /* Filter channel name */ |
| 0x0, /* Filter lcid - will be updated dynamically */ |
| 0x0, /* Filter rcid - will be updated dynamically */ |
| 0xFFFFFFFF, /* remote host ID */ |
| 0x0, /* Channel Context */ |
| 0xFFFFFFFF, /* All xports are enabled */ |
| }; |
| #endif |
| |
| /* Keep a list of registered transport for each edge allowed for this host |
| * ***IMPORTANT*** |
| * it should be safe to traverse this list without taking locks */ |
| static smem_list_type glink_registered_transports[GLINK_NUM_HOSTS]; |
| |
| /* List of supported hosts */ |
| const char* glink_hosts_supported[] = { "apss", |
| "mpss", |
| "lpass", |
| "dsps", |
| "wcnss", |
| "tz", |
| "rpm", |
| }; |
| |
| #if defined(GLINK_MEMORY_LOGGING) |
| static glink_mem_log_entry_type glink_mem_log_arr[GLINK_MEM_LOG_SIZE]; |
| static uint32 glink_mem_log_idx = 0; |
| static os_cs_type glink_mem_log_cs; |
| #endif |
| |
| static smem_list_type glink_link_notif_list; |
| static os_cs_type glink_link_notif_list_cs; |
| |
| /*=========================================================================== |
| GLOBAL FUNCTION DECLARATION |
| ===========================================================================*/ |
| /*=========================================================================== |
| LOCAL FUNCTION DEFINITIONS |
| ===========================================================================*/ |
| /*=========================================================================== |
| FUNCTION glinki_scan_channels_and_notify_discon |
| ===========================================================================*/ |
| /** |
| * Close all the channels belong to this transport |
| * This is helper function for glink_ssr |
| * |
| * @param[in] if_ptr pointer to transport interface |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| static void glinki_scan_channels_and_notify_discon |
| ( |
| glink_transport_if_type *if_ptr |
| ) |
| { |
| glink_channel_ctx_type *open_ch_ctx, *dummy_open_ch_ctx; |
| glink_core_xport_ctx_type *xport_ctx; |
| glink_remote_state_type remote_state; |
| |
| xport_ctx = if_ptr->glink_core_priv; |
| |
| /* Find channel in the open_list */ |
| glink_os_cs_acquire(&xport_ctx->channel_q_cs); |
| open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list); |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| |
| while(open_ch_ctx) |
| { |
| glink_os_cs_acquire(&xport_ctx->channel_q_cs); |
| open_ch_ctx->remote_state = GLINK_REMOTE_CH_SSR_RESET; |
| |
| dummy_open_ch_ctx = smem_list_next(open_ch_ctx); |
| |
| switch (open_ch_ctx->local_state) |
| { |
| case GLINK_LOCAL_CH_OPENED: |
| case GLINK_LOCAL_CH_OPENING: |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| /* local channel has called open at the moment. */ |
| open_ch_ctx->notify_state(open_ch_ctx, |
| open_ch_ctx->priv, |
| GLINK_REMOTE_DISCONNECTED); |
| break; |
| |
| case GLINK_LOCAL_CH_CLOSING: |
| /* Case when local client already closed channel |
| * but has not received ack yet */ |
| if_ptr->glink_core_if_ptr->rx_cmd_ch_close_ack(if_ptr, |
| open_ch_ctx->lcid); |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| break; |
| |
| case GLINK_LOCAL_CH_CLOSED: /* Channel fully closed - local, remote */ |
| case GLINK_LOCAL_CH_INIT: /* We had only remote open and waiting for local open */ |
| xport_ctx->channel_cleanup(open_ch_ctx); |
| smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx); |
| remote_state = open_ch_ctx->remote_state; |
| |
| if (remote_state != GLINK_REMOTE_CH_CLEANUP) |
| { |
| glink_os_free(open_ch_ctx); |
| } |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| break; |
| |
| default: |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| /* invalid local channel state */ |
| ASSERT(0); |
| } |
| |
| open_ch_ctx = dummy_open_ch_ctx; |
| } /* end while */ |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_xport_priority_comp |
| ===========================================================================*/ |
| /** |
| * Helper function for glinki_get_xport_from_prio. This will be provided to |
| * glinki_xports_find function. |
| * Return true if given transport has same priority |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] cond1 unused |
| * @param[in] priority glink transport priority to find |
| * |
| * @return TRUE if if_ptr priority matches |
| * FALSE otherwise |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static boolean glinki_xport_priority_comp |
| ( |
| glink_transport_if_type *if_ptr, |
| void *cond1, |
| uint32 priority, |
| void **out |
| ) |
| { |
| GLINK_OS_UNREFERENCED_PARAM( cond1 ); |
| GLINK_OS_UNREFERENCED_PARAM( out ); |
| |
| return if_ptr->glink_priority == (glink_xport_priority)priority; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_client_requested_xport_check |
| ===========================================================================*/ |
| /** |
| * check whether this is client requested xport or not |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] xport_name transport name to find |
| * @param[in] cond2 unused |
| * @param[in] out unused |
| * |
| * @return TRUE if transport name |
| * FALSE otherwise |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static boolean glinki_client_requested_xport_check |
| ( |
| glink_transport_if_type *if_ptr, |
| void *xport_name, |
| uint32 cond2, |
| void **out |
| ) |
| { |
| GLINK_OS_UNREFERENCED_PARAM( cond2 ); |
| GLINK_OS_UNREFERENCED_PARAM( out ); |
| |
| if (!glinki_xport_linkup(if_ptr)) |
| { |
| return FALSE; |
| } |
| |
| return 0 == glink_os_string_compare(if_ptr->glink_core_priv->xport, |
| (const char *)xport_name); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_update_best_xport |
| ===========================================================================*/ |
| /** |
| * Check whether given transport (if_ptr) has higher priority than |
| * priority user wants to check and update if it is true. |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] priority_param xport priority to compare |
| * @param[in] param2 unused |
| * @param[out] best_xport pointer to result xport |
| * |
| * @return FALSE all the time since this needs to iterate all transports |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static void glinki_update_best_xport |
| ( |
| glink_transport_if_type *if_ptr, |
| void *priority_param, |
| uint32 param2, |
| void **best_xport |
| ) |
| { |
| glink_xport_priority *priority; |
| |
| GLINK_OS_UNREFERENCED_PARAM( param2 ); |
| |
| ASSERT(best_xport && priority_param); |
| |
| priority = (glink_xport_priority*)priority_param; |
| |
| if (!glinki_xport_linkup(if_ptr)) |
| { |
| return; |
| } |
| |
| /* Given xport is best one if comparing xport doesn't exist */ |
| if (if_ptr->glink_priority < *priority) |
| { |
| *best_xport = (void*)if_ptr; |
| *priority = if_ptr->glink_priority; |
| } |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_notify_xport_ssr |
| ===========================================================================*/ |
| /** |
| * Notify this xport of ssr event and do ssr clean up |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] priority priority to check |
| * @param[in] cond2 unused |
| * @param[out] updated_xport pointer to result xport |
| * |
| * @return FALSE all the time since this needs to iterate all transports |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static void glinki_notify_xport_ssr |
| ( |
| glink_transport_if_type *if_ptr, |
| void *param1, |
| uint32 param2, |
| void **out |
| ) |
| { |
| GLINK_OS_UNREFERENCED_PARAM( param1 ); |
| GLINK_OS_UNREFERENCED_PARAM( param2 ); |
| GLINK_OS_UNREFERENCED_PARAM( out ); |
| /* xport is down. change the xport state */ |
| glink_os_cs_acquire(&if_ptr->glink_core_priv->status_cs); |
| if_ptr->glink_core_priv->status = GLINK_XPORT_REGISTERED; |
| |
| /* Let the xport know about ssr */ |
| if_ptr->ssr( if_ptr ); |
| |
| /* Invoke LINK_DOWN notification for any registered notifiers */ |
| glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_DOWN); |
| |
| /* Invoke REMOTE_DISCONNECT for all channels associated with if_ptr */ |
| glinki_scan_channels_and_notify_discon(if_ptr); |
| |
| glink_os_cs_release(&if_ptr->glink_core_priv->status_cs); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_check_xport_and_notify |
| ===========================================================================*/ |
| /** |
| * Notify this xport for link state change if applicable |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] link_notif_data_param parameter for link notif data |
| * @param[in] state link state to notify |
| * @param[out] out unused |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static void glinki_check_xport_and_notify |
| ( |
| glink_transport_if_type *if_ptr, |
| void *link_notif_data_param, |
| uint32 state, |
| void **out |
| ) |
| { |
| glink_core_xport_ctx_type *xport_ctx; |
| glink_link_notif_data_type *link_notif_data; |
| glink_link_info_type link_info; |
| |
| GLINK_OS_UNREFERENCED_PARAM( out ); |
| |
| ASSERT(link_notif_data_param && if_ptr->glink_core_priv); |
| |
| link_notif_data = (glink_link_notif_data_type *)link_notif_data_param; |
| xport_ctx = if_ptr->glink_core_priv; |
| |
| if (link_notif_data->xport == NULL || |
| 0 == glink_os_string_compare(xport_ctx->xport, link_notif_data->xport)) |
| { |
| /* xport not specified, or it is specified and matches the current xport */ |
| /* Invoke registered callback */ |
| link_info.xport = xport_ctx->xport; |
| link_info.remote_ss = xport_ctx->remote_ss; |
| link_info.link_state = (glink_link_state_type)state; |
| |
| link_notif_data->link_notifier(&link_info, link_notif_data->priv); |
| } |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_check_xport_link_up_and_notify |
| ===========================================================================*/ |
| /** |
| * Notify this xport for link state change if applicable |
| * |
| * @param[in] if_ptr transport interface pointer |
| * @param[in] link_notif_data_param parameter for link notif data |
| * @param[in] state link state to notify |
| * @param[out] out unused. but just passed as parameter |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| static void glinki_check_xport_link_up_and_notify |
| ( |
| glink_transport_if_type *if_ptr, |
| void *link_notif_data_param, |
| uint32 state, |
| void **out |
| ) |
| { |
| if (!glinki_xport_linkup(if_ptr)) |
| { |
| return; |
| } |
| |
| glinki_check_xport_and_notify(if_ptr, link_notif_data_param, state, out); |
| } |
| |
| /*=========================================================================== |
| EXTERNAL FUNCTION DEFINITIONS |
| ===========================================================================*/ |
| /*=========================================================================== |
| FUNCTION glink_init |
| |
| DESCRIPTION Initializes the GLink core library. |
| |
| ARGUMENTS None |
| |
| RETURN VALUE None |
| |
| SIDE EFFECTS None |
| ===========================================================================*/ |
| void glink_init(void) |
| { |
| uint32 i; |
| boolean cs_created = FALSE; |
| |
| #if defined(GLINK_MEMORY_LOGGING) |
| cs_created = glink_os_cs_init(&glink_mem_log_cs); |
| ASSERT(cs_created); |
| #elif defined(GLINK_OS_DEFINED_LOGGING) |
| OS_LOG_INIT(); |
| #endif |
| |
| smem_list_init(&glink_link_notif_list); |
| cs_created = glink_os_cs_init(&glink_link_notif_list_cs); |
| ASSERT(cs_created); |
| |
| /* Create/Initalize crtitical sections */ |
| for (i = 0; i < GLINK_NUM_HOSTS; ++i) |
| { |
| cs_created = glink_os_cs_init(&glink_transport_q_cs[i]); |
| ASSERT(cs_created); |
| smem_list_init(&glink_registered_transports[i]); |
| } |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_add_ch_to_xport |
| ===========================================================================*/ |
| /** |
| * Add remote/local channel context to xport open channel queue |
| * |
| * @param[in] if_ptr Pointer to xport if on which channel is to |
| * be opened |
| * @param[in] req_if_ptr Pointer to xport if on which channel |
| * actually wants to open |
| * @param[in] ch_ctx channel context |
| * @param[out] allocated_ch_ctx Pointer to channel context pointer |
| * @param[in] local_open flag to determine if channel is opened |
| * locally or remotely |
| * @param[in] migrated_ch_prio negotiated xport priority |
| * (used to send priority via remote_open_ack to |
| * remote side) |
| * |
| * @return G-Link standard error type |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| glink_err_type glinki_add_ch_to_xport |
| ( |
| glink_transport_if_type *if_ptr, |
| glink_channel_ctx_type *ch_ctx, |
| glink_channel_ctx_type **allocated_ch_ctx, |
| unsigned int local_open, |
| glink_xport_priority migrated_ch_prio |
| ) |
| { |
| glink_err_type status; |
| glink_channel_ctx_type *open_ch_ctx; |
| glink_core_xport_ctx_type *xport_ctx; |
| boolean valid_open_call; |
| |
| if ( if_ptr == NULL || |
| ch_ctx->name[0] == '\0' || |
| allocated_ch_ctx == NULL ) |
| { |
| return GLINK_STATUS_INVALID_PARAM; |
| } |
| |
| xport_ctx = if_ptr->glink_core_priv; |
| |
| /* See if channel already exists in open_list */ |
| glink_os_cs_acquire(&xport_ctx->channel_q_cs); |
| |
| open_ch_ctx = glinki_find_ch_ctx_by_name(xport_ctx, |
| ch_ctx->name, |
| (boolean)local_open, |
| &valid_open_call); |
| |
| if ( !valid_open_call ) |
| { |
| glink_os_free(ch_ctx); |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| return GLINK_STATUS_FAILURE; |
| } |
| |
| if (!open_ch_ctx) |
| { |
| /* check if a new channel can be added */ |
| if ((uint32)smem_list_count(&xport_ctx->open_list) >= xport_ctx->max_lcid) |
| { |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| glink_os_free(ch_ctx); |
| return GLINK_STATUS_OUT_OF_RESOURCES; |
| } |
| |
| /* Channel not in the list - it was not previously opened */ |
| ch_ctx->if_ptr = if_ptr; |
| *allocated_ch_ctx = ch_ctx; |
| |
| /* Set channel state */ |
| if (local_open) |
| { |
| /* This is a local open */ |
| ch_ctx->local_state = GLINK_LOCAL_CH_OPENING; |
| } |
| else |
| { |
| ch_ctx->remote_state = GLINK_REMOTE_CH_OPENED; |
| } |
| |
| glink_os_cs_init(&ch_ctx->tx_cs); |
| glink_os_cs_init(&ch_ctx->qos_cs); |
| |
| /* make sure next LCID is not used in currently open channels */ |
| open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list); |
| |
| while (open_ch_ctx) |
| { |
| if (open_ch_ctx->lcid == xport_ctx->free_lcid) |
| { |
| xport_ctx->free_lcid++; |
| |
| if (xport_ctx->free_lcid >= xport_ctx->max_lcid) |
| { |
| xport_ctx->free_lcid = 1; |
| } |
| |
| open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list); |
| continue; |
| } |
| |
| open_ch_ctx = smem_list_next(open_ch_ctx); |
| } |
| |
| ch_ctx->lcid = xport_ctx->free_lcid; |
| |
| /* Append the channel to the transport interface's open_list */ |
| smem_list_append(&if_ptr->glink_core_priv->open_list, ch_ctx); |
| |
| /* release lock before context switch otherwise it is causing deadlock */ |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| |
| /* Send the OPEN command to transport */ |
| if (local_open) |
| { |
| status = if_ptr->tx_cmd_ch_open(if_ptr, ch_ctx->lcid, |
| ch_ctx->name, |
| migrated_ch_prio); |
| } |
| else |
| { |
| /* initialize channel resources */ |
| status = xport_ctx->channel_init(ch_ctx); |
| |
| if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, ch_ctx->rcid, migrated_ch_prio); |
| } |
| |
| if (status != GLINK_STATUS_SUCCESS) |
| { |
| /* Remove the channel from the transport interface's open_list */ |
| xport_ctx->free_lcid--; |
| glinki_dequeue_item(&if_ptr->glink_core_priv->open_list, |
| ch_ctx, |
| &xport_ctx->channel_q_cs); |
| |
| /* free the ch_ctx structure and return */ |
| xport_ctx->channel_cleanup(ch_ctx); |
| glink_os_free(ch_ctx); |
| } |
| else |
| { |
| //Update the Filter |
| glinki_update_logging_filter(*allocated_ch_ctx, FALSE); |
| } |
| |
| return status; |
| } |
| |
| if (local_open) |
| { |
| /* LOCAL OPEN REQUEST */ |
| |
| ch_ctx->rcid = open_ch_ctx->rcid; |
| ch_ctx->lcid = open_ch_ctx->lcid; |
| ch_ctx->pintents = open_ch_ctx->pintents; |
| ch_ctx->if_ptr = open_ch_ctx->if_ptr; |
| |
| if (ch_ctx->pintents != NULL) |
| { |
| ch_ctx->pintents->ch_ctx = ch_ctx; |
| } |
| |
| ch_ctx->remote_state = open_ch_ctx->remote_state; |
| ch_ctx->local_state = GLINK_LOCAL_CH_OPENING; |
| |
| /* release lock before context switch otherwise it is causing |
| * deadlock */ |
| smem_list_delete(&xport_ctx->open_list, open_ch_ctx); |
| smem_list_append(&xport_ctx->open_list, ch_ctx); |
| |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| |
| glink_os_free(open_ch_ctx); |
| *allocated_ch_ctx = ch_ctx; |
| |
| /* Send open cmd to transport */ |
| status = if_ptr->tx_cmd_ch_open(if_ptr, |
| ch_ctx->lcid, |
| ch_ctx->name, |
| migrated_ch_prio); |
| } |
| else |
| { |
| /* REMOTE OPEN REQUEST */ |
| open_ch_ctx->rcid = ch_ctx->rcid; |
| *allocated_ch_ctx = open_ch_ctx; |
| status = xport_ctx->channel_init(open_ch_ctx); |
| |
| if (status == GLINK_STATUS_SUCCESS) |
| { |
| open_ch_ctx->remote_state = GLINK_REMOTE_CH_OPENED; |
| } |
| |
| /* release lock before context switch otherwise it is causing deadlock */ |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| |
| /* Send ACK to transport */ |
| if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, |
| open_ch_ctx->rcid, |
| migrated_ch_prio); |
| |
| if (status == GLINK_STATUS_SUCCESS) |
| { |
| /* Inform the client */ |
| if (open_ch_ctx->local_state == GLINK_LOCAL_CH_OPENED) |
| { |
| open_ch_ctx->notify_state(open_ch_ctx, |
| open_ch_ctx->priv, |
| GLINK_CONNECTED); |
| } |
| } |
| |
| glink_os_free(ch_ctx); |
| } /* end If - else (local_open) */ |
| |
| /* If the channel was added to be closed later by channel migration |
| do not update the filter */ |
| if ( status == GLINK_STATUS_SUCCESS ) |
| { |
| //Update the Filter - Reset Boolean=FALSE |
| glinki_update_logging_filter( *allocated_ch_ctx, FALSE ); |
| } |
| |
| return status; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_channel_fully_opened |
| ===========================================================================*/ |
| /** |
| * Check whether this channel is fully opened or not (local & remote) |
| * This also checks transport status |
| * |
| * @param[in] handle glink channel handle |
| * |
| * @return TRUE, if channel is fully opened |
| * FASLE, otherwise |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| boolean glinki_channel_fully_opened |
| ( |
| glink_handle_type handle |
| ) |
| { |
| boolean ch_fully_opened = TRUE; |
| |
| if (!glinki_xport_linkup(handle->if_ptr)) |
| { |
| return FALSE; |
| } |
| |
| glink_os_cs_acquire( &handle->if_ptr->glink_core_priv->channel_q_cs ); |
| |
| if (handle->local_state != GLINK_LOCAL_CH_OPENED || |
| handle->remote_state != GLINK_REMOTE_CH_OPENED) |
| { |
| ch_fully_opened = FALSE; |
| } |
| |
| glink_os_cs_release( &handle->if_ptr->glink_core_priv->channel_q_cs ); |
| |
| return ch_fully_opened; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glink_core_register_transport |
| |
| DESCRIPTION Transport calls this API to register its interface with GLINK |
| Core |
| |
| ARGUMENTS *if_ptr Pointer to interface instance; must be unique |
| for each edge |
| |
| *cfg Pointer to transport configuration structure. |
| |
| RETURN VALUE Standard GLINK error codes. |
| |
| SIDE EFFECTS None |
| ===========================================================================*/ |
| glink_err_type glink_core_register_transport |
| ( |
| glink_transport_if_type *if_ptr, |
| glink_core_transport_cfg_type *cfg |
| ) |
| { |
| unsigned int remote_host = 0; |
| glink_core_xport_ctx_type *xport_ctx; |
| |
| /* Param validation */ |
| if (if_ptr == NULL || |
| cfg == NULL || |
| cfg->name == NULL || |
| cfg->remote_ss == NULL || |
| cfg->version == NULL || |
| cfg->version_count == 0 || |
| cfg->max_cid == 0) |
| { |
| GLINK_LOG_ERROR_EVENT( GLINK_EVENT_REGISTER_XPORT, "", "", "", |
| GLINK_STATUS_INVALID_PARAM); |
| return GLINK_STATUS_INVALID_PARAM; |
| } |
| |
| if(if_ptr->tx_cmd_version == NULL || |
| if_ptr->tx_cmd_version_ack == NULL || |
| if_ptr->set_version == NULL || |
| if_ptr->tx_cmd_ch_open == NULL || |
| if_ptr->tx_cmd_ch_close == NULL || |
| if_ptr->tx_cmd_ch_remote_open_ack == NULL || |
| if_ptr->tx_cmd_ch_remote_close_ack == NULL || |
| if_ptr->ssr == NULL) |
| { |
| GLINK_LOG_ERROR_EVENT( GLINK_EVENT_REGISTER_XPORT, "", |
| cfg->name, |
| cfg->remote_ss, |
| GLINK_STATUS_INVALID_PARAM ); |
| return GLINK_STATUS_INVALID_PARAM;; |
| } |
| |
| remote_host = glinki_find_remote_host(cfg->remote_ss); |
| |
| if(remote_host == GLINK_NUM_HOSTS ) |
| { |
| /* Unknown transport name trying to register with GLink */ |
| GLINK_LOG_ERROR_EVENT( GLINK_EVENT_REGISTER_XPORT, "", |
| cfg->name, |
| cfg->remote_ss, |
| GLINK_STATUS_INVALID_PARAM ); |
| return GLINK_STATUS_INVALID_PARAM; |
| } |
| |
| /* Set the glink_core_if_ptr to point to the default interface */ |
| if_ptr->glink_core_if_ptr = glink_core_get_default_interface(); |
| |
| /* Allocate/fill out the GLink private context data */ |
| { |
| xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type)); |
| if(xport_ctx == NULL) |
| { |
| GLINK_LOG_ERROR_EVENT( GLINK_EVENT_REGISTER_XPORT, "", |
| cfg->name, |
| cfg->remote_ss, |
| GLINK_STATUS_OUT_OF_RESOURCES ); |
| |
| return GLINK_STATUS_OUT_OF_RESOURCES; |
| } |
| |
| xport_ctx->xport = cfg->name; |
| xport_ctx->remote_ss = cfg->remote_ss; |
| xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */ |
| xport_ctx->max_lcid = cfg->max_cid; /* Max channel ID supported by transport */ |
| xport_ctx->version_array = cfg->version; |
| xport_ctx->version_indx = (int32)cfg->version_count - 1; |
| |
| glink_os_cs_init(&xport_ctx->channel_q_cs); |
| glink_os_cs_init(&xport_ctx->liid_cs); |
| glink_os_cs_init(&xport_ctx->status_cs); |
| |
| glink_os_cs_acquire(&xport_ctx->channel_q_cs); |
| smem_list_init(&xport_ctx->open_list); |
| glink_os_cs_release(&xport_ctx->channel_q_cs); |
| |
| /* Set the glink_core_if_ptr to point to the allocated structure */ |
| if_ptr->glink_core_priv = xport_ctx; |
| xport_ctx->status = GLINK_XPORT_REGISTERED; |
| } |
| |
| /* Push the transport interface into appropriate queue */ |
| glinki_enqueue_item(&glink_registered_transports[remote_host], |
| if_ptr, |
| &glink_transport_q_cs[remote_host]); |
| |
| GLINK_LOG_EVENT_NO_FILTER( GLINK_EVENT_REGISTER_XPORT, "", |
| xport_ctx->xport, |
| xport_ctx->remote_ss, |
| GLINK_STATUS_SUCCESS); |
| |
| return GLINK_STATUS_SUCCESS; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_register_link_notif_data |
| ===========================================================================*/ |
| /** |
| * Register link notification data |
| * |
| * @param[in] link_notif_data parameter for link notif data |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| void glinki_register_link_notif_data |
| ( |
| glink_link_notif_data_type *link_notif_data |
| ) |
| { |
| glinki_enqueue_item(&glink_link_notif_list, |
| (void *)link_notif_data, |
| &glink_link_notif_list_cs); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_deregister_link_notif_data |
| ===========================================================================*/ |
| /** |
| * Deregister link notification data |
| * |
| * @param[in] link_notif_data parameter for link notif data |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| void glinki_deregister_link_notif_data |
| ( |
| glink_link_notif_data_type *link_notif_data |
| ) |
| { |
| glinki_dequeue_item(&glink_link_notif_list, |
| (void *)link_notif_data, |
| &glink_link_notif_list_cs); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_scan_xports_and_notify |
| ===========================================================================*/ |
| /** |
| * Scan xports and notify link up state event |
| * |
| * @param[in] link_notif_data parameter for link notif data |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| void glinki_scan_xports_and_notify |
| ( |
| glink_link_notif_data_type *link_notif_data |
| ) |
| { |
| unsigned int remote_host; |
| glink_link_state_type link_state = GLINK_LINK_STATE_UP; |
| |
| ASSERT(link_notif_data); |
| |
| /* Find matching subsystem */ |
| for (remote_host = 0; remote_host < GLINK_NUM_HOSTS; ++remote_host) |
| { |
| if (link_notif_data->remote_ss != NULL && |
| 0 != glink_os_string_compare(glink_hosts_supported[remote_host], |
| link_notif_data->remote_ss)) |
| { |
| /* client is not interested in this remote SS */ |
| continue; |
| } |
| |
| glinki_xports_for_each(glink_hosts_supported[remote_host], |
| glinki_check_xport_link_up_and_notify, |
| link_notif_data, |
| link_state, |
| NULL); |
| } |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_scan_notif_list_and_notify |
| ===========================================================================*/ |
| /** |
| * Scan registered link notification list and notify of xport link state change |
| * |
| * @param[in] if_ptr pointer to xport interface |
| * @param[in] state link state to notify |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| void glinki_scan_notif_list_and_notify |
| ( |
| glink_transport_if_type *if_ptr, |
| glink_link_state_type state |
| ) |
| { |
| glink_link_notif_data_type *link_notif_data; |
| |
| glink_os_cs_acquire(&glink_link_notif_list_cs); |
| |
| for (link_notif_data = smem_list_first(&glink_link_notif_list); |
| link_notif_data != NULL; |
| link_notif_data = smem_list_next(link_notif_data)) |
| { |
| if( link_notif_data->remote_ss == NULL || |
| 0 == glink_os_string_compare( if_ptr->glink_core_priv->remote_ss, |
| link_notif_data->remote_ss ) ) |
| { |
| glinki_check_xport_and_notify(if_ptr, |
| link_notif_data, |
| (uint32)state, |
| NULL); |
| } |
| } |
| |
| glink_os_cs_release(&glink_link_notif_list_cs); |
| } /* glinki_scan_notif_list_and_notify */ |
| |
| /*=========================================================================== |
| FUNCTION glinki_ssr |
| ===========================================================================*/ |
| /** |
| * Notify all the xports of ssr event in this edge |
| * |
| * @param[in] remote_ss name of remote subsystem |
| * |
| * @return NONE |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| void glink_ssr(const char* remote_ss) |
| { |
| glinki_xports_for_each(remote_ss, |
| glinki_notify_xport_ssr, |
| NULL, |
| 0, |
| NULL); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_xport_linkup |
| ===========================================================================*/ |
| /** |
| * Check whether this transport is in linkup state or not |
| * |
| * @param[in] if_ptr transport interface pointer |
| * |
| * @return TRUE if this xport is in link up state |
| * FALSE otherwise |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| boolean glinki_xport_linkup |
| ( |
| glink_transport_if_type *if_ptr |
| ) |
| { |
| return if_ptr->glink_core_priv->status == GLINK_XPORT_LINK_UP; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_xports_for_each |
| ===========================================================================*/ |
| /** |
| * Scan all the transports in given edge and perform client's function for each |
| * transport |
| * |
| * @param[in] remote_ss name of remote subsystem, NULL string not accepted |
| * @param[in] client_ex_fn client function to perform on each xport |
| * @param[in] param1 first parameter to use in client_ex_fn |
| * @param[in] param2 second parameter to use in client_ex_fn |
| * @param[out] out value to return in case client wants |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| * |
| * This routine ASSUMES it is safe to traverse the glink_registered_transports |
| * without a lock. This is only true if the following conditions are met |
| * 1) Only append/traverse operations are allowed on this list (No insert, delete) |
| * 2) Append should make sure at no instance of time we have an uninitialized |
| * pointer(next) along the list |
| */ |
| /*=========================================================================*/ |
| void glinki_xports_for_each |
| ( |
| const char *remote_ss, |
| glink_client_ex_fn client_ex_fn, |
| void *param1, |
| uint32 param2, |
| void **out |
| ) |
| { |
| glink_transport_if_type *if_iter_ptr; |
| |
| uint32 remote_host = glinki_find_remote_host(remote_ss); |
| |
| ASSERT(remote_host < GLINK_NUM_HOSTS); |
| |
| |
| for(if_iter_ptr = smem_list_first(&glink_registered_transports[remote_host]); |
| if_iter_ptr != NULL; |
| if_iter_ptr = smem_list_next(if_iter_ptr)) |
| { |
| client_ex_fn(if_iter_ptr, param1, param2, out); |
| } |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_xports_find |
| ===========================================================================*/ |
| /** |
| * Scan all the transports in given edge and finds transport that satisfy |
| * client's condition |
| * |
| * @param[in] remote_ss name of remote subsystem, NULL string not accepted |
| * @param[in] client_cond_fn client function to check if this transport is |
| * what client is looking for |
| * @param[in] cond1 first condition to use in client_ex_fn |
| * @param[in] cond2 second condition to use in client_ex_fn |
| * @param[out] out value to return in case client wants |
| * |
| * @return pointer to glink_transport_if_type struct |
| * NULL if there isn't any xport matches client's search condition |
| * |
| * @sideeffects None. |
| * |
| * This routine ASSUMES it is safe to traverse the glink_registered_transports |
| * without a lock. This is only true if the following conditions are met |
| * 1) Only append/traverse operations are allowed on this list (No insert/delete) |
| * 2) Append should make sure at no instance of time we have an uninitialized |
| * pointer(next) along the list |
| */ |
| /*=========================================================================*/ |
| glink_transport_if_type *glinki_xports_find |
| ( |
| const char *remote_ss, |
| glink_client_cond_fn client_cond_fn, |
| void *cond1, |
| uint32 cond2, |
| void **out |
| ) |
| { |
| glink_transport_if_type *if_iter_ptr; |
| |
| uint32 remote_host = glinki_find_remote_host(remote_ss); |
| |
| ASSERT(remote_host < GLINK_NUM_HOSTS); |
| |
| for (if_iter_ptr = smem_list_first(&glink_registered_transports[remote_host]); |
| if_iter_ptr != NULL; |
| if_iter_ptr = smem_list_next(if_iter_ptr)) |
| { |
| if(client_cond_fn(if_iter_ptr, cond1, cond2, out)) |
| { |
| break; |
| } |
| } |
| |
| return if_iter_ptr; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_ch_ctx_by_lcid |
| ===========================================================================*/ |
| /** |
| * Find channel context by lcid |
| * |
| * @param[in] xport_ctx Pointer to transport private context |
| * @param[in] lcid local channel ID |
| * |
| * @return pointer to glink channel context |
| * |
| * @sideeffects This function needs to be protected by channel_q_cs |
| * Caller is responsible grab/release mutex when calling this |
| */ |
| /*=========================================================================*/ |
| glink_channel_ctx_type *glinki_find_ch_ctx_by_lcid |
| ( |
| glink_core_xport_ctx_type *xport_ctx, |
| uint32 lcid |
| ) |
| { |
| glink_channel_ctx_type *open_ch_ctx; |
| |
| for (open_ch_ctx = smem_list_first(&xport_ctx->open_list); |
| open_ch_ctx; |
| open_ch_ctx = smem_list_next(open_ch_ctx)) |
| { |
| if (open_ch_ctx->lcid == lcid) |
| { |
| return open_ch_ctx; |
| } |
| } |
| |
| /* open_ch_ctx will be NULL here. Using this instead of ASSERT(0) |
| to avoid unreachable code warning */ |
| ASSERT( open_ch_ctx != NULL ); |
| return NULL; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_ch_ctx_by_rcid |
| ===========================================================================*/ |
| /** |
| * Find channel context by rcid |
| * |
| * @param[in] xport_ctx Pointer to transport private context |
| * @param[in] rcid remote channel ID |
| * |
| * @return pointer to glink channel context |
| * |
| * @sideeffects This function needs to be protected by channel_q_cs |
| * Caller is responsible grab/release mutex when calling this |
| */ |
| /*=========================================================================*/ |
| glink_channel_ctx_type *glinki_find_ch_ctx_by_rcid |
| ( |
| glink_core_xport_ctx_type *xport_ctx, |
| uint32 rcid |
| ) |
| { |
| glink_channel_ctx_type *open_ch_ctx; |
| |
| for (open_ch_ctx = smem_list_first(&xport_ctx->open_list); |
| open_ch_ctx; |
| open_ch_ctx = smem_list_next(open_ch_ctx)) |
| { |
| if (open_ch_ctx->rcid == rcid) |
| { |
| return open_ch_ctx; |
| } |
| } |
| |
| /* open_ch_ctx will be NULL here. Using this instead of ASSERT(0) |
| to avoid unreachable code warning */ |
| ASSERT( open_ch_ctx != NULL ); |
| return NULL; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_ch_ctx_by_name |
| ===========================================================================*/ |
| /** |
| * Find channel context by channel name, called by local/remote open function |
| * This function will also indicate (valid_open_call) if this open call would |
| * be valid or not |
| * |
| * @param[in] xport_ctx Pointer to transport private context |
| * @param[in] ch_name channel name |
| * @param[in] local_open flag to indicate this is local open call |
| * @param[out] valid_open_call tell whether this open call would be valid |
| * or not |
| * |
| * @return pointer to glink channel context |
| * NULL if channel doesn't exist |
| * |
| * @sideeffects This function needs to be protected by channel_q_cs |
| * Caller is responsible grab/release mutex when calling this |
| */ |
| /*=========================================================================*/ |
| glink_channel_ctx_type *glinki_find_ch_ctx_by_name |
| ( |
| glink_core_xport_ctx_type *xport_ctx, |
| const char *ch_name, |
| boolean local_open, |
| boolean *valid_open_call |
| ) |
| { |
| glink_channel_ctx_type *open_ch_ctx; |
| glink_channel_ctx_type *ch_ctx_found = NULL; |
| glink_remote_state_type remote_state; |
| glink_local_state_type local_state; |
| |
| ASSERT( valid_open_call != NULL ); |
| *valid_open_call = TRUE; |
| |
| for(open_ch_ctx = smem_list_first(&xport_ctx->open_list); |
| open_ch_ctx != NULL; |
| open_ch_ctx = smem_list_next(open_ch_ctx)) |
| { |
| remote_state = open_ch_ctx->remote_state; |
| local_state = open_ch_ctx->local_state; |
| |
| if ( 0 != glink_os_string_compare(open_ch_ctx->name, ch_name) || |
| remote_state == GLINK_REMOTE_CH_CLEANUP || |
| remote_state == GLINK_REMOTE_CH_SSR_RESET ) |
| { |
| continue; |
| } |
| |
| if ( ( local_open == TRUE && local_state == GLINK_LOCAL_CH_INIT ) || |
| ( local_open == FALSE && remote_state == GLINK_REMOTE_CH_INIT ) ) |
| { |
| /* Local/Remote side already opened channel */ |
| ch_ctx_found = open_ch_ctx; |
| } |
| else if ( ( local_open == TRUE && local_state != GLINK_LOCAL_CH_CLOSED ) || |
| ( local_open == FALSE && remote_state != GLINK_REMOTE_CH_CLOSED ) ) |
| { |
| /* Local/Remote side is trying to open channel without closing old one */ |
| *valid_open_call = FALSE; |
| break; |
| } |
| } |
| |
| return ch_ctx_found; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_remote_host |
| ===========================================================================*/ |
| /** |
| * return remote subsystem ID based on remote subsystem name |
| * |
| * @param[in] remote_ss remote subsystem name |
| * |
| * @return remote subsystem ID |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| uint32 glinki_find_remote_host |
| ( |
| const char *remote_ss |
| ) |
| { |
| uint32 remote_host; |
| |
| for(remote_host = 0; remote_host < GLINK_NUM_HOSTS; remote_host++) |
| { |
| if( 0 == glink_os_string_compare(glink_hosts_supported[remote_host], |
| remote_ss)) |
| { |
| /* Match found, break out of loop */ |
| break; |
| } |
| } |
| |
| return remote_host; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_best_xport |
| ===========================================================================*/ |
| /** |
| * This function gives best available transport for give edge |
| * |
| * @param[in] remote_host Index into glink_registered_transports array of |
| * registered transports list per edge |
| * |
| * @return pointer to glink_transport_if_type |
| * Null, if transport not found |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| glink_transport_if_type *glinki_find_best_xport |
| ( |
| const char *remote_ss |
| ) |
| { |
| glink_transport_if_type *best_if_ptr = NULL; |
| glink_xport_priority priority = GLINK_MIN_PRIORITY; |
| |
| glinki_xports_for_each(remote_ss, |
| glinki_update_best_xport, |
| (void *)&priority, |
| 0, |
| (void **)&best_if_ptr); |
| |
| return best_if_ptr; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_requested_xport |
| ===========================================================================*/ |
| /** |
| * Find requested or best transport depending on client's request |
| * |
| * @param[in] xport_name name of transport |
| * @param[in] remote_ss remote subsystem name |
| * @param[in] open_ch_option option client gave when called glink_open |
| * @param[out] suggested_priority best xport priority glink suggests |
| * |
| * @return pointer to glink_transport_if_type struct |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| glink_transport_if_type *glinki_find_requested_xport |
| ( |
| const char *xport_name, |
| const char *remote_ss, |
| uint32 open_ch_option, |
| glink_xport_priority *suggested_priority |
| ) |
| { |
| glink_transport_if_type *best_xport = glinki_find_best_xport(remote_ss); |
| glink_transport_if_type *xport_found = NULL; |
| |
| *suggested_priority = GLINK_INVALID_PRIORITY; |
| |
| if (!xport_name) |
| { |
| if (best_xport) |
| { |
| *suggested_priority = best_xport->glink_priority; |
| } |
| |
| return best_xport; |
| } |
| |
| xport_found = glinki_xports_find(remote_ss, |
| glinki_client_requested_xport_check, |
| (void *)xport_name, |
| 0, |
| NULL); |
| |
| if (!xport_found) |
| { |
| return NULL; |
| } |
| |
| if ((open_ch_option & GLINK_OPT_INITIAL_XPORT) != 0) |
| { |
| *suggested_priority = best_xport->glink_priority; |
| } |
| else |
| { |
| /* Client is not willing to migrate to better transport */ |
| *suggested_priority = xport_found->glink_priority; |
| } |
| |
| return xport_found; |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_find_xport_by_priority |
| ===========================================================================*/ |
| /** |
| * This function returns glink_transport_if pointer based on transport priority |
| * |
| * @param[in] prio glink xport prio |
| * @param[in] remote_ss remote subsytem name |
| * |
| * @return pointer to glink_transport_if_type struct |
| * NULL, if it's not registered or transport not found with |
| * the priority |
| * |
| * @sideeffects NONE |
| */ |
| /*=========================================================================*/ |
| glink_transport_if_type *glinki_find_xport_by_priority |
| ( |
| glink_xport_priority prio, |
| const char *remote_ss |
| ) |
| { |
| return glinki_xports_find(remote_ss, |
| glinki_xport_priority_comp, |
| NULL, |
| (uint32)prio, |
| NULL); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_enqueue_item |
| ===========================================================================*/ |
| /** |
| * Enqueue item to smem list in protected context |
| * |
| * @param[in] smem_list smem list to enqueue |
| * @param[in] item item to queue |
| * @param[in] cs mutex to protect the list |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| void glinki_enqueue_item |
| ( |
| smem_list_type *smem_list_ptr, |
| void *item, |
| os_cs_type *cs |
| ) |
| { |
| glink_os_cs_acquire(cs); |
| smem_list_append(smem_list_ptr, item); |
| glink_os_cs_release(cs); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_dequeue_item |
| ===========================================================================*/ |
| /** |
| * Dequeue item from smem list in protected context |
| * |
| * @param[in] smem_list smem list to dequeue from |
| * @param[in] item item to dequeue |
| * @param[in] cs mutex to protect the list |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| void glinki_dequeue_item |
| ( |
| smem_list_type *smem_list_ptr, |
| void *item, |
| os_cs_type *cs |
| ) |
| { |
| glink_os_cs_acquire(cs); |
| smem_list_delete(smem_list_ptr, item); |
| glink_os_cs_release(cs); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_acquire_edge_lock |
| ===========================================================================*/ |
| /** |
| * Acquires the transport_q_cs lock for the specified edge |
| * |
| * @param[in] remote_ss Name of the remote sub system on the edge |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| void glinki_acquire_edge_lock(const char *ss_name) |
| { |
| uint32 remote_host; |
| remote_host = glinki_find_remote_host(ss_name); |
| glink_os_cs_acquire(&glink_transport_q_cs[remote_host]); |
| } |
| |
| /*=========================================================================== |
| FUNCTION glinki_release_edge_lock |
| ===========================================================================*/ |
| /** |
| * Releases the transport_q_cs lock for the specified edge |
| * |
| * @param[in] remote_ss Name of the remote sub system on the edge |
| * |
| * @return None. |
| * |
| * @sideeffects None. |
| */ |
| /*=========================================================================*/ |
| void glinki_release_edge_lock(const char *ss_name) |
| { |
| uint32 remote_host; |
| remote_host = glinki_find_remote_host(ss_name); |
| glink_os_cs_release(&glink_transport_q_cs[remote_host]); |
| } |
| |
| #if defined(GLINK_MEMORY_LOGGING) |
| /* ============ Internal Logging API ================ */ |
| void glink_mem_log |
| ( |
| glink_log_event_type type, |
| const char *msg, |
| const char *xport, |
| const char *remote_ss, |
| uint32 param |
| ) |
| { |
| #ifdef DEBUG_GLINK |
| dprintf(INFO, "%s:%u, event:%d, msg:%s, xport:%s, remote_ss:%s, param:%u\n", func, line, type, msg, xport, remote_ss, param); |
| #endif |
| } |
| #endif |
| |
| #ifdef FEATURE_TRACER_PACKET |
| /*=========================================================================== |
| FUNCTION glink_tracer_packet_log_pctx_pkt |
| ===========================================================================*/ |
| /** |
| * Log tracer packet event. Tracer packet is included in glink_core_tx_pkt |
| * and needs to use vprovider to extract it |
| * |
| * @param[in] pctx pointer to glink_core_tx_pkt_type |
| * @param[in] event_id event_id |
| * |
| * @return None |
| * |
| * @sideeffects None |
| */ |
| /*=========================================================================*/ |
| void glink_tracer_packet_log_pctx_pkt |
| ( |
| glink_core_tx_pkt_type *pctx, |
| uint32 event_id |
| ) |
| { |
| tracer_pkt_result_type tracer_pkt_log_result; |
| void *tracer_pkt_data; |
| size_t tracer_pkt_size; |
| |
| tracer_pkt_data = pctx->vprovider(pctx->iovec, 0, &tracer_pkt_size); |
| |
| if (tracer_pkt_size != pctx->size) |
| { |
| GLINK_LOG_EVENT_NO_FILTER( GLINK_EVENT_TXV_INVALID_BUFFER, "", "", "", |
| tracer_pkt_size); |
| } |
| |
| tracer_pkt_log_result = tracer_packet_log_event(tracer_pkt_data, (uint16)event_id); |
| if (tracer_pkt_log_result != TRACER_PKT_STATUS_SUCCESS) |
| { |
| GLINK_LOG_EVENT_NO_FILTER( GLINK_EVENT_TRACER_PKT_FAILURE, "", "", "", |
| tracer_pkt_log_result); |
| } |
| } |
| #endif |
| |
| /*=========================================================================== |
| FUNCTION glinki_update_logging_filter |
| ===========================================================================*/ |
| /** |
| * Update/Reset the logging filter if the name and remote host of the |
| * logging filter matches to that of the passed channel context |
| * |
| * @param[in] chnl_ctx Channel content to match/compare |
| * @param[in] reset Indicate Update(FALSE) or Reset(TRUE) |
| * |
| * @return None. |
| */ |
| /*=========================================================================*/ |
| #if defined(GLINK_OS_DEFINED_LOGGING) || defined(GLINK_MEMORY_LOGGING) |
| void glinki_update_logging_filter |
| ( |
| glink_channel_ctx_type *chnl_ctx, |
| boolean reset |
| ) |
| { |
| if ( ( log_filter_cfg.ch_filter_status == TRUE ) && |
| ( (chnl_ctx) != NULL ) && |
| ( glink_os_string_compare( (chnl_ctx)->name, |
| log_filter_cfg.ch_name) == 0 ) && |
| ( log_filter_cfg.remote_host == |
| glinki_find_remote_host((chnl_ctx)->if_ptr->glink_core_priv->remote_ss) ) |
| ) |
| { |
| if (reset == FALSE) /* Update the Filter */ |
| { |
| log_filter_cfg.ch_ctx = (chnl_ctx); |
| log_filter_cfg.ch_lcid = (chnl_ctx)->lcid; |
| log_filter_cfg.ch_rcid = (chnl_ctx)->rcid; |
| } |
| else /* Reset the Filter */ |
| { |
| log_filter_cfg.ch_ctx = NULL; |
| log_filter_cfg.ch_lcid = 0; |
| log_filter_cfg.ch_rcid = 0; |
| log_filter_cfg.remote_host = (uint32)-1; |
| } |
| } |
| } |
| |
| #else |
| void glinki_update_logging_filter(glink_channel_ctx_type *chnl_ctx, boolean reset) |
| { |
| GLINK_OS_UNREFERENCED_PARAM( chnl_ctx ); |
| GLINK_OS_UNREFERENCED_PARAM( reset ); |
| } |
| #endif |