platform: msm_shared: Add GLink support
GLink is a protocol for IPC communication and is needed
for LK to talk to RPM processor
Change-Id: I2f4a44ac0d9950d5a5046c6b4aa341821a8dc663
diff --git a/platform/msm_shared/glink/glink_api.c b/platform/msm_shared/glink/glink_api.c
new file mode 100644
index 0000000..24f777d
--- /dev/null
+++ b/platform/msm_shared/glink/glink_api.c
@@ -0,0 +1,1532 @@
+/* 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.h>
+#include <glink_rpm.h>
+#include <glink_os_utils.h>
+#include <glink_internal.h>
+#include <glink_vector.h>
+#include <glink_channel_migration.h>
+#include <smem_list.h>
+#include <smem_type.h>
+
+#define GLINK_NOT_INITIALIZED 0
+#define GLINK_INITIALIZED 1
+
+/*===========================================================================
+ GLOBAL DATA DECLARATIONS
+===========================================================================*/
+int glink_core_status = GLINK_NOT_INITIALIZED;
+
+os_cs_type *glink_transport_q_cs;
+os_cs_type *glink_mem_log_cs;
+
+glink_mem_log_entry_type glink_mem_log_arr[GLINK_MEM_LOG_SIZE];
+uint32 glink_mem_log_idx = 0;
+
+/* Keep a list of registered transport for each edge allowed for this host */
+smem_list_type glink_registered_transports[GLINK_NUM_HOSTS];
+
+smem_list_type glink_link_notif_list;
+
+/* List of supported hosts */
+const char* glink_hosts_supported[] = { "apss",
+ "mpss",
+ "lpass",
+ "dsps",
+ "wcnss",
+ "tz",
+ "rpm",
+ };
+
+/* Forward function declarations */
+void glinki_free_intents(glink_channel_ctx_type *open_ch_ctx);
+
+/*===========================================================================
+ LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+glink_err_type glinki_add_ch_to_xport
+(
+ glink_transport_if_type *if_ptr,
+ glink_transport_if_type *req_if_ptr,
+ glink_channel_ctx_type *ch_ctx,
+ glink_channel_ctx_type **allocated_ch_ctx,
+ unsigned int local_open,
+ boolean migration_state,
+ glink_xport_priority migrated_ch_prio
+)
+{
+ glink_err_type status = 0;
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *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 = smem_list_first(&if_ptr->glink_core_priv->open_list);
+ while(open_ch_ctx != NULL)
+ {
+ if (strcmp(open_ch_ctx->name, ch_ctx->name) == 0)
+ {
+ /* We've found a channel name is already in the list of open channel */
+ /* increase reference open count for channel */
+ *allocated_ch_ctx = open_ch_ctx;
+ open_ch_ctx->ref_count++;
+
+ /* Case A: Channel was opened before on the same host */
+ if((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) && local_open) {
+
+ open_ch_ctx->req_if_ptr = req_if_ptr;
+
+ /* Copy local open ctx params */
+ open_ch_ctx->notify_rx = ch_ctx->notify_rx;
+ open_ch_ctx->notify_rxv = ch_ctx->notify_rxv;
+ open_ch_ctx->notify_tx_done = ch_ctx->notify_tx_done;
+ open_ch_ctx->notify_state = ch_ctx->notify_state;
+ open_ch_ctx->notify_rx_intent_req = ch_ctx->notify_rx_intent_req;
+ open_ch_ctx->notify_rx_intent = ch_ctx->notify_rx_intent;
+ open_ch_ctx->notify_rx_sigs = ch_ctx->notify_rx_sigs;
+ open_ch_ctx->priv = ch_ctx->priv;
+ open_ch_ctx->ch_open_options = ch_ctx->ch_open_options;
+
+ /* release lock before context switch otherwise it is causing
+ * deadlock */
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+ /* Send open cmd to transport */
+ status = if_ptr->tx_cmd_ch_open(if_ptr,
+ open_ch_ctx->lcid, open_ch_ctx->name,
+ open_ch_ctx->req_if_ptr->glink_priority);
+ }
+ else if ((open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN) &&
+ (!local_open))
+ {
+ /* Case B: Channel was opened on this end and we got a remote open */
+ open_ch_ctx->rcid = ch_ctx->rcid;
+
+ status = xport_ctx->channel_init(open_ch_ctx);
+
+ /* release lock before context switch otherwise it is causing deadlock */
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+ if (status == GLINK_STATUS_SUCCESS)
+ {
+ /* Send ACK to transport */
+ if_ptr->tx_cmd_ch_remote_open_ack(if_ptr, open_ch_ctx->rcid, migrated_ch_prio);
+ }
+ } else if ((open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE)
+ && (local_open)) {
+ /* Allocate new channel context */
+ break; /* code would break out of loop and create new ch ctx */
+ } else {
+ /* Can't handle this state */
+ ASSERT(0);
+ }
+
+ break;
+ } /* end if match found */
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }/* end while */
+
+ if (open_ch_ctx != NULL)
+ {
+ glink_os_free(ch_ctx);
+
+ /* connect channel here if state is local open and remote open request
+ * comes up and channel migration is done; channel will be connected in
+ * remote_open_ack if channel state is remote open and local open
+ * request comes up */
+ if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN &&
+ migration_state == FALSE && status == GLINK_STATUS_SUCCESS)
+ {
+ /* Set the channel state to OPEN */
+ open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+ /* Inform the client */
+ open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+ GLINK_CONNECTED);
+ }
+ }
+ else
+ {
+ /* 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->state = GLINK_CH_STATE_LOCAL_OPEN;
+ ch_ctx->req_if_ptr = req_if_ptr;
+ }
+ else {
+ ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN;
+ }
+
+ glink_os_cs_init(&ch_ctx->tx_cs);
+
+ /* Append the channel to the transport interface's open_list */
+ ch_ctx->ref_count++;
+ ch_ctx->lcid = xport_ctx->free_lcid;
+ xport_ctx->free_lcid++;
+ 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,
+ ch_ctx->req_if_ptr->glink_priority);
+ }
+ else
+ {
+ /* initialize channel resources */
+ status = xport_ctx->channel_init(ch_ctx);
+
+ /* ACK the transport for remote open */
+ if (status == GLINK_STATUS_SUCCESS)
+ {
+ 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--;
+
+ glink_os_cs_acquire(&xport_ctx->channel_q_cs);
+ smem_list_delete(&if_ptr->glink_core_priv->open_list, ch_ctx);
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+ /* free the ch_ctx structure and return */
+ xport_ctx->channel_cleanup(ch_ctx);
+ glink_os_free(ch_ctx);
+ }
+ }
+
+ return status;
+}
+
+/** Default implementation of optional callbacks */
+
+static void glink_default_notify_rx_sigs
+(
+ glink_handle_type handle,
+ const void *priv,
+ uint32 prev,
+ uint32 curr
+)
+{
+ return;
+}
+
+static void glinki_call_link_notifier
+(
+ glink_link_notif_data_type *link_notif_data,
+ glink_core_xport_ctx_type *xport_ctx,
+ glink_link_state_type state
+)
+{
+ glink_link_info_type link_info;
+
+ ASSERT(xport_ctx);
+ ASSERT(link_notif_data);
+
+ link_info.xport = xport_ctx->xport;
+ link_info.remote_ss = xport_ctx->remote_ss;
+ link_info.link_state = state;
+ link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+}
+
+static uint32 glinki_find_remote_host
+(
+ const char *remote_ss
+)
+{
+ uint32 remote_host;
+ ASSERT(remote_ss);
+
+ for(remote_host = 0;
+ remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+ remote_host++) {
+ if( 0 == strcmp(glink_hosts_supported[remote_host], remote_ss) ) {
+ /* Match found, break out of loop */
+ break;
+ }
+ }
+ return remote_host;
+}
+
+static void glinki_check_xport_and_notify
+(
+ glink_link_notif_data_type *link_notif_data,
+ glink_core_xport_ctx_type *xport_ctx,
+ glink_link_state_type state
+)
+{
+ glink_link_info_type link_info;
+
+ ASSERT(xport_ctx);
+ ASSERT(link_notif_data);
+
+ link_info.xport = xport_ctx->xport;
+ link_info.remote_ss = xport_ctx->remote_ss;
+ link_info.link_state = state;
+
+ if(link_notif_data->xport == NULL ||
+ 0 == strcmp(xport_ctx->xport, link_notif_data->xport)) {
+ /* xport not specified, or it is specified and matches the current xport */
+ /* Invoke registered callback */
+ link_notif_data->link_notifier(&link_info, link_notif_data->priv);
+ }
+}
+
+
+static void glinki_scan_xports_and_notify
+(
+ glink_link_notif_data_type *link_notif_data
+)
+{
+ unsigned int remote_host;
+ glink_transport_if_type *if_ptr;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(link_notif_data);
+
+ /* Find matching subsystem */
+ if(link_notif_data->remote_ss) {
+ remote_host = glinki_find_remote_host(link_notif_data->remote_ss);
+
+ /* Find the xport and give link UP notification */
+ if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+ if(if_ptr == NULL) {
+ /* No registered xports at this time, return without doing anything */
+ return;
+ }
+
+ if(link_notif_data->xport) {
+ do {
+ xport_ctx = if_ptr->glink_core_priv;
+ if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+ /* Match found, break out of loop */
+ break;
+ }
+ }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+ if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+ /* Invoke registered callback */
+ glinki_call_link_notifier(link_notif_data, xport_ctx,
+ GLINK_LINK_STATE_UP);
+ }
+ } else {
+ /* No xport has been specified, invoke notifier for all registered
+ * xports */
+ do {
+ xport_ctx = if_ptr->glink_core_priv;
+ if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+ /* Invoke registered callback */
+ glinki_call_link_notifier(link_notif_data, xport_ctx,
+ GLINK_LINK_STATE_UP);
+ }
+ }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+ }
+ } else {
+ /* No remote ss is specified, invoke notifier for all remote_ss */
+ for(remote_host = 0;
+ remote_host < sizeof(glink_hosts_supported)/sizeof(char *);
+ remote_host++) {
+ /* Find the xport and give link UP notification */
+ if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+ if(if_ptr == NULL) {
+ /* No registered xports at this time, continue with next remote_ss */
+ continue;
+ }
+
+ if(link_notif_data->xport) {
+ do {
+ xport_ctx = if_ptr->glink_core_priv;
+ if( 0 == strcmp(xport_ctx->xport, link_notif_data->xport) ) {
+ /* Match found, break out of loop */
+ break;
+ }
+ }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+
+ if((if_ptr != NULL) && (xport_ctx->status == GLINK_XPORT_LINK_UP)) {
+ /* Invoke registered callback */
+ glinki_call_link_notifier(link_notif_data, xport_ctx,
+ GLINK_LINK_STATE_UP);
+ }
+ } else {
+ /* No xport has been specified, invoke notifier for all registered
+ * xports */
+ do {
+ xport_ctx = if_ptr->glink_core_priv;
+ if(xport_ctx->status == GLINK_XPORT_LINK_UP) {
+ /* Invoke registered callback */
+ glinki_call_link_notifier(link_notif_data, xport_ctx,
+ GLINK_LINK_STATE_UP);
+ }
+ }while ((if_ptr = smem_list_next(if_ptr)) != NULL);
+ }
+ } /* end for remote_host */
+ }/* end if else (link_notif_data->remote_ss) */
+} /* glinki_scan_xports_and_notify */
+
+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_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
+
+ link_notif_data = smem_list_first(&glink_link_notif_list);
+
+ if(link_notif_data == NULL) {
+ /* list empty */
+ return;
+ }
+
+ do {
+ if(link_notif_data->remote_ss &&
+ 0 == strcmp(xport_ctx->remote_ss, link_notif_data->remote_ss)) {
+ /* remote_ss specified and matches */
+ glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+ } else if(link_notif_data->remote_ss == NULL) {
+ /* remote_ss not specified, invoke link notif for any remote_ss */
+ if(link_notif_data->xport) {
+ glinki_check_xport_and_notify(link_notif_data, xport_ctx, state);
+ } /* if else link_notif_data->xport */
+ } /* if else link_notif_data->remote_ss */
+ } while ( (link_notif_data = smem_list_next(link_notif_data)) != NULL);
+
+} /* glinki_scan_notif_list_and_notify */
+
+void glinki_scan_channels_and_notify_discon
+(
+ glink_transport_if_type *if_ptr
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ 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);
+ while(open_ch_ctx != NULL)
+ {
+ /* Found channel, transition it to appropriate state based
+ * on current state */
+ if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+ open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN;
+
+ /* Inform the client */
+ open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+ GLINK_REMOTE_DISCONNECTED);
+ } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+ /* Local side never opened the channel */
+ /* Free channel resources */
+ xport_ctx->channel_cleanup(open_ch_ctx);
+
+ smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+ glink_os_free(open_ch_ctx);
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }/* end while */
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+void glink_ssr(const char* remote_ss)
+{
+ unsigned int remote_host;
+ glink_transport_if_type *if_ptr;
+
+ remote_host = glinki_find_remote_host(remote_ss);
+
+ /* Scan through the registered interfaces with the crashing ss
+ and let the clients know about the crash via LINK_DOWN
+ notification followed by REMOTE_DISCONNECT */
+ if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+
+ while(if_ptr != NULL) {
+ /* 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);
+
+ /* Let the xport know about ssr */
+ if_ptr->ssr(if_ptr);
+
+ if_ptr = smem_list_next(if_ptr);
+ }
+}
+
+
+/*===========================================================================
+ 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;
+
+ glink_mem_log_cs = glink_os_cs_create();
+
+ glink_core_status = GLINK_INITIALIZED;
+
+ /* Create/Initalize crtitical sections */
+ glink_transport_q_cs = glink_os_cs_create();
+ if(glink_transport_q_cs == NULL) {
+ return;
+ }
+
+ glink_os_cs_acquire(glink_transport_q_cs);
+ for(i= 0; i < sizeof(glink_registered_transports)/sizeof(smem_list_type);
+ i++)
+ {
+ smem_list_init(&glink_registered_transports[i]);
+ }
+ glink_os_cs_release(glink_transport_q_cs);
+}
+
+/*===========================================================================
+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)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+ GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ if(cfg->name == NULL ||
+ cfg->remote_ss == NULL ||
+ cfg->version == NULL ||
+ cfg->version_count == 0 ||
+ cfg->max_cid == 0)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, "", "",
+ 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->tx_cmd_set_sigs == NULL ||
+ if_ptr->ssr == NULL)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+ cfg->remote_ss, GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;;
+ }
+
+
+ /* Allocate/fill out the GLink Core interface structure */
+ {
+ glink_core_if_type *core_if = glink_os_calloc(sizeof(glink_core_if_type));
+ if(core_if == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+ cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+ core_if->link_up = glink_link_up;
+ core_if->rx_cmd_version = glink_rx_cmd_version;
+ core_if->rx_cmd_version_ack = glink_rx_cmd_version_ack;
+ core_if->rx_cmd_ch_remote_open = glink_rx_cmd_ch_remote_open;
+ core_if->rx_cmd_ch_open_ack = glink_rx_cmd_ch_open_ack;
+ core_if->rx_cmd_ch_close_ack = glink_rx_cmd_ch_close_ack;
+ core_if->rx_cmd_ch_remote_close = glink_rx_cmd_ch_remote_close;
+ core_if->ch_state_local_trans = glink_ch_state_local_trans;
+ core_if->rx_put_pkt_ctx = glink_rx_put_pkt_ctx;
+ core_if->rx_cmd_remote_sigs = glink_rx_cmd_remote_sigs;
+ core_if->tx_resume = glink_tx_resume;
+ core_if->set_core_version = glink_set_core_version;
+
+ /* Set the glink_core_if_ptr to point to the allocated structure */
+ if_ptr->glink_core_if_ptr = core_if;
+ }
+
+ /* Allocate/fill out the GLink private context data */
+ {
+ xport_ctx = glink_os_calloc(sizeof(glink_core_xport_ctx_type));
+ if(xport_ctx == NULL) {
+ /* Free previously allocated memory */
+ glink_os_free(if_ptr->glink_core_if_ptr);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, cfg->name,
+ cfg->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+
+ glink_os_string_copy(xport_ctx->xport, cfg->name,
+ sizeof(xport_ctx->xport));
+ glink_os_string_copy(xport_ctx->remote_ss, cfg->remote_ss,
+ sizeof(xport_ctx->xport));
+ xport_ctx->free_lcid = 1; /* lcid 0 is reserved for invalid channel */
+ xport_ctx->version_array = cfg->version;
+ xport_ctx->version_indx = cfg->version_count - 1;
+
+ glink_os_cs_init(&xport_ctx->channel_q_cs);
+ glink_os_cs_init(&xport_ctx->liid_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 */
+ 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_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+ glink_os_cs_acquire(glink_transport_q_cs);
+ smem_list_append(&glink_registered_transports[remote_host], if_ptr);
+ glink_os_cs_release(glink_transport_q_cs);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, NULL, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in] link_id Pointer to the configuration structure for the
+ * xport(link) to be monitored. See glink.h
+ * @param[in] priv Callback data returned to client when callback
+ * is invoked.
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Puts the callback in a queue which gets scanned when a
+ * transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+ glink_link_id_type *link_id,
+ void* priv
+)
+{
+ glink_link_notif_data_type* link_notif_data;
+ unsigned int remote_host;
+
+ /* Input validation */
+ ASSERT(link_id != NULL);
+
+ /* Make sure client provided us with the correct version of the input
+ * structure */
+ if(link_id->version != GLINK_LINK_ID_VER || link_id->link_notifier == NULL) {
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* Save the callback on the notification list */
+ if((link_notif_data = glink_os_malloc(sizeof(glink_link_notif_data_type)))
+ == NULL) {
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Check for remote_ss validity */
+ if(link_id->remote_ss != NULL) {
+ remote_host = glinki_find_remote_host(link_id->remote_ss);
+
+ if(remote_host == sizeof(glink_hosts_supported)/sizeof(char *)) {
+ glink_os_free(link_notif_data);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+ }
+
+ link_notif_data->xport = link_id->xport;
+ link_notif_data->remote_ss = link_id->remote_ss;
+ link_notif_data->link_notifier = link_id->link_notifier;
+ link_notif_data->priv = priv; /* private client data */
+
+ /* Append the request to the list for link UP/DOWN notifications */
+ smem_list_append(&glink_link_notif_list, link_notif_data);
+
+ /* Scan the list of available transport to see if this link is already up */
+ glinki_scan_xports_and_notify(link_notif_data);
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in] handle Callback handler returned by
+ * glink_register_link_state_cb
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Removes the callback in a queue which gets scanned when a
+ * transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+ glink_link_handle_type handle
+)
+{
+ ASSERT(handle);
+
+ smem_list_delete(&glink_link_notif_list,
+ (glink_link_notif_data_type*)handle);
+
+ glink_os_free(handle);
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * 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
+ *
+ * @sideeffects NONE
+ */
+glink_transport_if_type* glink_get_best_xport
+(
+ unsigned int remote_host
+)
+{
+ glink_transport_if_type *if_ptr = NULL, *best_if_ptr = NULL;
+ glink_xport_priority priority = GLINK_MIN_PRIORITY;
+ glink_core_xport_ctx_type *xport_ctx = NULL;
+
+ best_if_ptr = if_ptr = smem_list_first(
+ &glink_registered_transports[remote_host]);
+
+ while(if_ptr != NULL)
+ {
+ /* check if priority of current transport is higher than
+ * current highest priority (0 = highest priority)
+ */
+ xport_ctx = if_ptr->glink_core_priv;
+ if( xport_ctx->status == GLINK_XPORT_LINK_UP &&
+ if_ptr->glink_priority < priority )
+ {
+ best_if_ptr = if_ptr;
+ priority = if_ptr->glink_priority;
+ }
+
+ if_ptr = smem_list_next(if_ptr);
+ } /* end while() */
+
+ return best_if_ptr;
+}
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in] cfg_ptr Pointer to the configuration structure for the
+ * GLink. See glink.h
+ * @param[out] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Allocates channel resources and informs remote host about
+ * channel open.
+ */
+glink_err_type glink_open
+(
+ glink_open_config_type *cfg_ptr,
+ glink_handle_type *handle
+)
+{
+ glink_transport_if_type *if_ptr, *req_if_ptr;
+ glink_channel_ctx_type *ch_ctx;
+ unsigned int remote_host;
+
+ /* Param validation */
+ if(cfg_ptr == NULL)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+ GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ if(cfg_ptr->remote_ss == NULL ||
+ cfg_ptr->name == NULL ||
+ cfg_ptr->notify_state == NULL)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, NULL, "", "",
+ GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* Evaluate the equivalent edge name->enum for future use */
+ remote_host = glinki_find_remote_host(cfg_ptr->remote_ss);
+
+ if(remote_host == GLINK_NUM_HOSTS ) {
+ /* Unknown transport name trying to register with GLink */
+ GLINK_LOG_EVENT(GLINK_EVENT_REGISTER_XPORT, cfg_ptr->name, "",
+ cfg_ptr->remote_ss, GLINK_STATUS_INVALID_PARAM);
+
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* Allocate and initialize channel info structure */
+ ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+ if(ch_ctx == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, "",
+ "", GLINK_STATUS_OUT_OF_RESOURCES);
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Fill in the channel info structure */
+ glink_os_string_copy(ch_ctx->name, cfg_ptr->name, sizeof(ch_ctx->name));
+ ch_ctx->priv = cfg_ptr->priv;
+ ch_ctx->notify_rx = cfg_ptr->notify_rx;
+ ch_ctx->notify_rxv = cfg_ptr->notify_rxv;
+ ch_ctx->notify_tx_done = cfg_ptr->notify_tx_done;
+ ch_ctx->notify_state = cfg_ptr->notify_state;
+ ch_ctx->notify_rx_intent_req = cfg_ptr->notify_rx_intent_req;
+ ch_ctx->notify_rx_intent = cfg_ptr->notify_rx_intent;
+ ch_ctx->notify_rx_sigs = cfg_ptr->notify_rx_sigs;
+ ch_ctx->ch_open_options = cfg_ptr->options;
+ ch_ctx->notify_rx_abort = cfg_ptr->notify_rx_abort;
+ ch_ctx->notify_tx_abort = cfg_ptr->notify_tx_abort;
+
+ if (ch_ctx->notify_rx_sigs == NULL) {
+ /* set default callback */
+ ch_ctx->notify_rx_sigs = glink_default_notify_rx_sigs;
+ }
+
+ glink_os_cs_acquire(glink_transport_q_cs);
+
+ /* Check to see if requested transport is available */
+ for (if_ptr = smem_list_first(&glink_registered_transports[remote_host]);
+ if_ptr != NULL;
+ if_ptr = smem_list_next(if_ptr))
+ {
+ glink_core_xport_ctx_type *xport_ctx = if_ptr->glink_core_priv;
+ glink_channel_ctx_type *allocated_ch_ctx;
+
+ if (xport_ctx->status == GLINK_XPORT_LINK_UP &&
+ (cfg_ptr->transport == NULL ||
+ 0 == strcmp(cfg_ptr->transport, xport_ctx->xport)) &&
+ xport_ctx->verify_open_cfg(ch_ctx))
+ {
+ glink_err_type status;
+
+ if(cfg_ptr->transport == NULL)
+ {
+ /* get best available transport */
+ if_ptr = req_if_ptr = glink_get_best_xport(remote_host);
+ }
+ else
+ {
+ if(cfg_ptr->options & GLINK_OPT_INITIAL_XPORT)
+ {
+ /* xport suggested by client is optional.
+ * get best available xport */
+ req_if_ptr = glink_get_best_xport(remote_host);
+ }
+ else
+ {
+ req_if_ptr = if_ptr;
+ }
+ }
+ /* Xport match found */
+ status = glinki_add_ch_to_xport( if_ptr,
+ req_if_ptr,
+ ch_ctx,
+ &allocated_ch_ctx,
+ TRUE,
+ TRUE,
+ if_ptr->glink_priority );
+
+ if (status == GLINK_STATUS_SUCCESS) {
+ /* Set the handle and return */
+ *handle = allocated_ch_ctx;
+ }
+ else {
+ *handle = NULL;
+ }
+
+ glink_os_cs_release(glink_transport_q_cs);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, ch_ctx->name, xport_ctx->xport,
+ xport_ctx->remote_ss, status);
+ return status;
+ }
+ } /* end for() */
+
+ glink_os_cs_release(glink_transport_q_cs);
+
+ /* Code gets here if we are not able to find reqeusted transport */
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN, cfg_ptr->name, cfg_ptr->transport,
+ cfg_ptr->remote_ss, GLINK_STATUS_NO_TRANSPORT);
+ glink_os_free(ch_ctx);
+ return GLINK_STATUS_NO_TRANSPORT;
+}
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+ glink_handle_type handle
+)
+{
+ glink_err_type status;
+ glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+ glink_ch_state_type ch_state;
+
+ if(handle == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ ch_state = handle->state;
+
+ /* Check to see if channel is in open/opening state */
+ if (ch_state != GLINK_CH_STATE_OPEN &&
+ ch_state != GLINK_CH_STATE_LOCAL_OPEN &&
+ ch_state != GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE &&
+ ch_state != GLINK_CH_STATE_REMOTE_OPEN)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, ch_state);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ /* Transition to closing */
+ //handle->state = GLINK_CH_STATE_CLOSING;
+
+ /* Send CLOSE cmd to the transport interface */
+ status = handle->if_ptr->tx_cmd_ch_close(handle->if_ptr, handle->lcid);
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, status);
+ return status;
+
+}
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] *data Pointer to the data buffer to be transmitted
+ *
+ * @param[in] size Size of buffer
+ *
+ * @param[in] req_intent Whether to block and request for remote rx intent in
+ * case it is not available for this pkt tx
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ const void *data,
+ size_t size,
+ uint32 options
+)
+{
+ return glink_txv(handle, pkt_priv, (void*)data, size,
+ &glink_dummy_tx_vprovider, NULL, options);
+
+}
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] *iovec Pointer to the vector buffer to be transmitted
+ *
+ * @param[in] size Size of buffer
+ *
+ * @param[in] vprovider Buffer provider for virtual space
+ *
+ * @param[in] pprovider Buffer provider for physical space
+ *
+ * @param[in] req_intent Whether to block and request for remote rx intent in
+ * case it is not available for this pkt tx
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ void *iovec,
+ size_t size,
+ glink_buffer_provider_fn vprovider,
+ glink_buffer_provider_fn pprovider,
+ uint32 options
+)
+{
+ glink_err_type status;
+ glink_core_tx_pkt_type pctx;
+ boolean req_intent = options & GLINK_TX_REQ_INTENT;
+ glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+ /* Input validation */
+ if(handle == NULL || iovec == NULL || size == 0 ||
+ (vprovider == NULL && pprovider == NULL)) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* Make sure channel is in OPEN state */
+ if(handle->state != GLINK_CH_STATE_OPEN )
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ /* Protect the entire tx operation under a lock as a client may call
+ tx in different thread context */
+ glink_os_cs_acquire(&handle->tx_cs);
+
+ pctx.pkt_priv = pkt_priv;
+ pctx.size = size;
+ pctx.size_remaining = size;
+ pctx.vprovider = vprovider;
+ pctx.pprovider = pprovider;
+
+ if (vprovider == &glink_dummy_tx_vprovider)
+ {
+ pctx.data = (void*)iovec;
+ pctx.iovec = &pctx;
+ }
+ else
+ {
+ pctx.data = (void*)iovec;
+ pctx.iovec = iovec;
+ }
+
+ status = xport_ctx->use_rm_intent(handle, &pctx, req_intent);
+
+ /* Call transport API to transmit data */
+ while (pctx.size_remaining != 0 && status == GLINK_STATUS_SUCCESS)
+ {
+ status = handle->if_ptr->tx(handle->if_ptr, handle->lcid, &pctx);
+ }
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_TX, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, status);
+
+ glink_os_cs_release(&handle->tx_cs);
+ return status;
+}
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] size Size of buffer
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ size_t size
+)
+{
+ glink_err_type status;
+ glink_rx_intent_type *lc_intent;
+ glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+ size_t tmp;
+
+ /* Input validation */
+ if(handle == NULL || size == 0) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* short circuit for intentless mode */
+ if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+ return GLINK_STATUS_FAILURE;
+ }
+
+ /* Make sure channel is in OPEN state */
+ if(handle->state != GLINK_CH_STATE_OPEN)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ /* Allocate an intent structure */
+ lc_intent = glink_os_calloc(sizeof(glink_rx_intent_type));
+ if(lc_intent == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+
+ glink_os_cs_acquire(&handle->if_ptr->glink_core_priv->liid_cs);
+
+ /* Call transport API to allocate rx intent buffer */
+ status = handle->if_ptr->allocate_rx_intent(handle->if_ptr, size, lc_intent);
+ if(status != GLINK_STATUS_SUCCESS) {
+ glink_os_free(lc_intent);
+ glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, status);
+ return status;
+ }
+
+ if (handle->notify_rxv == NULL &&
+ (lc_intent->vprovider(lc_intent->iovec, 0, &tmp) == NULL || tmp < size)) {
+ /* Allocate bounce buffer for non-vectored Rx */
+ lc_intent->data = glink_os_malloc(size);
+
+ if(lc_intent->data == NULL) {
+ handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+ glink_os_free(lc_intent);
+ glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name,
+ xport_ctx->xport, xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+ }
+
+ /* push the intent on local queue. Do this before calling tx cmd
+ as transport may try to read data into the newly queued rx_buffer */
+ lc_intent->iid = handle->if_ptr->glink_core_priv->liid;
+ lc_intent->size = size;
+ lc_intent->pkt_priv = pkt_priv;
+ glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+ smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+ glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+ /* Call transport API to queue rx intent */
+ /* Increment the local intent ID counter associated with this channel */
+ handle->if_ptr->glink_core_priv->liid++;
+
+ status = handle->if_ptr->tx_cmd_local_rx_intent(handle->if_ptr,
+ handle->lcid, size, lc_intent->iid);
+ if(status != GLINK_STATUS_SUCCESS) {
+ /* Failure */
+ glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+ smem_list_delete(&handle->pintents->local_intent_q, lc_intent);
+ glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+ handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+ glink_os_free(lc_intent->data);
+ glink_os_free(lc_intent);
+ }
+ glink_os_cs_release(&handle->if_ptr->glink_core_priv->liid_cs);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_Q_RX_INTENT, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, status);
+ return status;
+}
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *ptr Pointer to the received buffer
+ *
+ * @param[in] reuse Reuse intent
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+ glink_handle_type handle,
+ const void *ptr,
+ boolean reuse
+)
+{
+ glink_rx_intent_type *lc_intent;
+ glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+
+ /* Input validation */
+ if(handle == NULL || ptr == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* short circuit for intentless mode */
+ if(xport_ctx->xport_capabilities & GLINK_CAPABILITY_INTENTLESS) {
+ return GLINK_STATUS_SUCCESS;
+ }
+
+ /* Make sure channel is in OPEN state */
+ if(handle->state != GLINK_CH_STATE_OPEN)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ /* Free the intent */
+ lc_intent = smem_list_first(&handle->pintents->local_intent_client_q);
+ while(lc_intent != NULL) {
+ size_t tmp;
+
+ if(lc_intent->iovec == ptr || (handle->notify_rxv == NULL &&
+ (lc_intent->data == ptr ||
+ ptr == lc_intent->vprovider(lc_intent->iovec, 0, &tmp)))) {
+
+ uint32 iid;
+
+ /* Found intent, delete it */
+ glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+ smem_list_delete(&handle->pintents->local_intent_client_q, lc_intent);
+ glink_os_cs_release(&handle->pintents->intent_q_cs);
+
+ iid = lc_intent->iid;
+
+ if (reuse)
+ {
+ lc_intent->used = 0;
+
+ glink_os_cs_acquire(&handle->pintents->intent_q_cs);
+ smem_list_append(&handle->pintents->local_intent_q, lc_intent);
+ glink_os_cs_release(&handle->pintents->intent_q_cs);
+ }
+ else
+ {
+ /* Free the intent */
+ handle->if_ptr->deallocate_rx_intent(handle->if_ptr, lc_intent);
+ if(lc_intent->data) {
+ /* Free the bounce buffer if we had allocated one */
+ glink_os_free(lc_intent->data);
+ }
+ glink_os_free(lc_intent);
+ }
+
+ /* Note that the actual buffer, lc_intent->data, was allocated by the
+ * transport and should be freed by the xport. We should not touch it */
+ /* Let the xport know we are done with the buffer */
+ handle->if_ptr->tx_cmd_local_rx_done(handle->if_ptr, handle->lcid,
+ iid, reuse);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+ return GLINK_STATUS_SUCCESS;
+ }
+ lc_intent = smem_list_next(lc_intent);
+ }
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_RX_DONE, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+}
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] sig_value 32 bit signal word
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_set
+(
+ glink_handle_type handle,
+ uint32 sig_value
+)
+{
+ glink_core_xport_ctx_type *xport_ctx = handle->if_ptr->glink_core_priv;
+ glink_err_type status;
+
+ /* Input validation */
+ if(handle == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ /* Make sure channel is in OPEN state */
+ if(handle->state != GLINK_CH_STATE_OPEN)
+ {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_SET, handle->name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_FAILURE);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ status = handle->if_ptr->tx_cmd_set_sigs(handle->if_ptr, handle->lcid,
+ sig_value);
+ if(GLINK_STATUS_SUCCESS == status) {
+ /* Update local copy of local control signal state */
+ handle->local_sigs = sig_value;
+ }
+
+ return status;
+}
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_local_get
+(
+ glink_handle_type handle,
+ uint32 *sig_value
+)
+{
+ /* Input validation */
+ if(handle == NULL || sig_value == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_L_GET, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ *sig_value = handle->local_sigs;
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_remote_get
+(
+ glink_handle_type handle,
+ uint32 *sig_value
+)
+{
+ /* Input validation */
+ if(handle == NULL || sig_value == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_SIG_R_GET, NULL, "",
+ "", GLINK_STATUS_INVALID_PARAM);
+ return GLINK_STATUS_INVALID_PARAM;
+ }
+
+ *sig_value = handle->remote_sigs;
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/*================= RESTRICTED API ==========================*/
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+ glink_handle_type handle
+)
+{
+ ASSERT(handle);
+
+ if(handle->if_ptr->poll) {
+ return handle->if_ptr->poll(handle->if_ptr);
+ }
+ return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] mask Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in] platform_struct Any platform specific into that transport may
+ require
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+ glink_handle_type handle,
+ boolean mask,
+ void *platform_struct
+)
+{
+ ASSERT(handle);
+
+ if(handle->if_ptr->mask_rx_irq) {
+ return handle->if_ptr->mask_rx_irq(handle->if_ptr, mask);
+ }
+ return GLINK_STATUS_FAILURE;
+}
+
+/**
+ * This API waits until link is down.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_wait_link_down
+(
+ glink_handle_type handle
+)
+{
+ ASSERT(handle && handle->if_ptr && handle->if_ptr->wait_link_down);
+
+ return handle->if_ptr->wait_link_down(handle->if_ptr) ?
+ GLINK_STATUS_SUCCESS : GLINK_STATUS_FAILURE;
+}
+
+/* ============ Internal Logging API ================ */
+void glink_mem_log
+(
+ const char *func,
+ uint32 line,
+ 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
+}
diff --git a/platform/msm_shared/glink/glink_core_if.c b/platform/msm_shared/glink/glink_core_if.c
new file mode 100644
index 0000000..3c66369
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_if.c
@@ -0,0 +1,983 @@
+/* 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_os_utils.h"
+#include "glink.h"
+#include "glink_internal.h"
+#include "glink_core_if.h"
+#include "smem_list.h"
+#include "glink_channel_migration.h"
+
+
+#define FEATURE_CH_MIGRATION_FREE
+
+void glinki_scan_notif_list_and_notify
+(
+ glink_transport_if_type *if_ptr,
+ glink_link_state_type state
+);
+
+/*===========================================================================
+ GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+ LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION glink_process_negotiation_complete
+===========================================================================*/
+/**
+
+ This is called when negotiation is complete.
+ It will set the version and call link up callback to notify
+
+
+ @param[in] xport_ctx transport context
+
+ @param[in] if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ @param[in] version negotiated version
+
+ @param[in] features negotiated with local side
+
+ @return None
+ @sideeffects None.
+ @dependencies None.
+*/
+/*=========================================================================*/
+static void glink_process_negotiation_complete
+(
+ glink_core_xport_ctx_type *xport_ctx,
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ /* Version/Feautre can be negotiated both in ver_req and ver_ack
+ * Only go through process once in case they are negotiated
+ * in ver_req before receiving ver_ack */
+ if( xport_ctx->status == GLINK_XPORT_LINK_UP )
+ {
+ return;
+ }
+
+ /* setup core based on transport capabilities*/
+ xport_ctx->xport_capabilities = if_ptr->set_version( if_ptr,
+ version,
+ features );
+ glink_core_setup(if_ptr);
+
+ /* transport is ready to open channels */
+ if_ptr->glink_core_priv->status = GLINK_XPORT_LINK_UP;
+
+ /* Scan the notification list to check is we have to let any registered
+ * clients know that link came online */
+ glinki_scan_notif_list_and_notify(if_ptr, GLINK_LINK_STATE_UP);
+}
+
+static void glink_dummy_ch_migration_notification_cb
+(
+ glink_handle_type handle,
+ const void *priv,
+ glink_channel_event_type event
+)
+{
+}
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION glink_link_up
+
+DESCRIPTION Indicates that transport is now ready to start negotiation
+ using the v0 configuration
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_link_up
+(
+ glink_transport_if_type *if_ptr
+)
+{
+ const glink_core_version_type *version_array;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ version_array = xport_ctx->version_array;
+
+ /* Update the transport state */
+ if_ptr->glink_core_priv->status = GLINK_XPORT_NEGOTIATING;
+
+ /* Start the negtiation */
+ if_ptr->tx_cmd_version(if_ptr, version_array->version,
+ version_array->features);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_LINK_UP, NULL, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_version
+
+DESCRIPTION Receive transport version for remote-initiated version
+ negotiation
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Remote Version
+
+ features Remote Features
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ const glink_core_version_type *ver;
+ uint32 negotiated_features;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* The version to use must be a subset of supported version and features
+ * on this host and remote host */
+ ver = &xport_ctx->version_array[xport_ctx->version_indx];
+ ASSERT(ver);
+
+ if (version == ver->version)
+ {
+ /* Call the transport's negotiation function */
+ negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+ /* If negotiated features match the provided features, version nogetiation
+ * is complete */
+ if(negotiated_features == features)
+ {
+ /* send version ack before allowing to open channels */
+ if_ptr->tx_cmd_version_ack(if_ptr, version, features);
+
+ glink_process_negotiation_complete( xport_ctx, if_ptr,
+ version, features );
+ return;
+ }
+ else
+ {
+ if_ptr->tx_cmd_version_ack(if_ptr, version, negotiated_features);
+ }
+ }
+ else
+ {
+ /* Next time use older version */
+ ver = &xport_ctx->version_array[xport_ctx->version_indx];
+
+ /* Versions don't match, return ACK with the feature set that we support */
+ if_ptr->tx_cmd_version_ack(if_ptr, ver->version, ver->features);
+ }
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_version_ack
+
+DESCRIPTION Receive ACK to previous glink_transport_if::tx_cmd_version
+ command
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Remote Version
+
+ features Remote Features
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ const glink_core_version_type* ver;
+ uint32 negotiated_features;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Check to see if version returned by remote end is supported by
+ * this host. Remote side would have acked only when the version/features
+ * sent by this host did not match the remote */
+
+ ver = &xport_ctx->version_array[xport_ctx->version_indx];
+ ASSERT(ver);
+
+ if (ver->version == version)
+ {
+ /* Call the transport's negotiation function */
+ negotiated_features = ver->negotiate_features(if_ptr, ver, features);
+
+ if(negotiated_features != features)
+ {
+ /* Continue negotiating */
+ if_ptr->tx_cmd_version(if_ptr, version, negotiated_features);
+ }
+ else
+ {
+ glink_process_negotiation_complete( xport_ctx, if_ptr,
+ version, features );
+ }
+ }
+ else
+ {
+ while (ver->version > version)
+ {
+ /* Next time use older version */
+ ASSERT(xport_ctx->version_indx > 0);
+ xport_ctx->version_indx--;
+ ver = &xport_ctx->version_array[xport_ctx->version_indx];
+ }
+
+ /* Versions don't match, return ACK with the feature set that we support */
+ if_ptr->tx_cmd_version(if_ptr, ver->version, ver->features);
+ }
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_remote_open
+
+DESCRIPTION Receive remote channel open request; Calls
+ glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ *name String name for logical channel
+
+ prio xport priority requested by remote side
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+ glink_transport_if_type *if_ptr,
+ uint32 rcid,
+ const char *name,
+ glink_xport_priority priority
+)
+{
+ glink_channel_ctx_type *remote_ch_ctx;
+ glink_channel_ctx_type *allocated_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+ glink_err_type status;
+ glink_xport_priority negotiated_prio;
+ boolean migration_state = TRUE;
+
+ ASSERT(if_ptr != NULL);
+ ASSERT(name != NULL);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+ glink_transport_if_type *present_if_ptr = NULL;
+ boolean channel_exist = FALSE;
+ glink_channel_ctx_type *present_ch_ctx = NULL;
+ /* search if channel with given name exists locally */
+ channel_exist = glinki_local_channel_exists(if_ptr, &present_if_ptr, name, &present_ch_ctx, TRUE);
+
+ /* start channel migration negotiation only if channel exists on local side
+ * for negotiation AND channel is willing to migrate */
+ if(channel_exist &&
+ (present_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+ {
+ /* channel exists on one of the xports for given remote ss */
+ current_prio = present_ch_ctx->req_if_ptr->glink_priority;
+ negotiated_prio = glinki_negotiate_ch_migration(priority, current_prio);
+
+ /* if current channel is open in same xport as negotiated xport
+ * local side wont migrate. Set migration flag to FALSE */
+ if(negotiated_prio == present_if_ptr->glink_priority)
+ {
+ migration_state = FALSE;
+ }
+ }
+ else if(channel_exist)
+ {
+ /* channel exists but channel does not want to be moved to another xport.
+ channel is set in stone */
+ negotiated_prio = present_if_ptr->glink_priority;
+ migration_state = FALSE;
+ }
+ else
+ {
+ /* channel does not exist on local side as yet
+ * return negotiated prio as current xport prio on which
+ * remote open request is received */
+ negotiated_prio = if_ptr->glink_priority;
+ migration_state = FALSE;
+ }
+#else
+ negotiated_prio = if_ptr->glink_priority;
+ migration_state = FALSE;
+#endif
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Allocate and initialize channel info structure */
+ remote_ch_ctx = glink_os_calloc(sizeof(glink_channel_ctx_type));
+ if(remote_ch_ctx == NULL) {
+ GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_OUT_OF_RESOURCES);
+ ASSERT(0);
+ }
+
+ /* Fill in the channel info structure */
+ glink_os_string_copy(remote_ch_ctx->name, name, sizeof(remote_ch_ctx->name));
+ remote_ch_ctx->rcid = rcid;
+
+ status = glinki_add_ch_to_xport(if_ptr, NULL, remote_ch_ctx,
+ &allocated_ch_ctx, FALSE,
+ migration_state, negotiated_prio);
+ ASSERT(status == GLINK_STATUS_SUCCESS);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_RM_CH_OPEN, name, xport_ctx->xport,
+ xport_ctx->remote_ss, GLINK_STATUS_SUCCESS);
+
+#ifndef FEATURE_CH_MIGRATION_FREE
+
+ /* We are done with channel migration negotiation at this stage
+ * Tag all channels with given name on xports other than negotiated
+ * xport for deletion */
+ glinki_tag_ch_for_deletion(if_ptr, name, negotiated_prio);
+
+ if(migration_state == TRUE)
+ {
+ glink_channel_ctx_type *new_ch_ctx;
+
+ /* create a new channel context as current channel will be migrated */
+ new_ch_ctx = (glink_channel_ctx_type *)
+ glink_os_calloc(sizeof(glink_channel_ctx_type));
+
+ /* Fill in the channel info structure */
+ new_ch_ctx->req_if_ptr =
+ glinki_get_xport_from_prio(negotiated_prio,
+ if_ptr->glink_core_priv->remote_ss);
+ glink_os_string_copy(new_ch_ctx->name, present_ch_ctx->name,
+ sizeof(present_ch_ctx->name));
+ new_ch_ctx->priv = present_ch_ctx->priv;
+ new_ch_ctx->notify_rx = present_ch_ctx->notify_rx;
+ new_ch_ctx->notify_rxv = present_ch_ctx->notify_rxv;
+ new_ch_ctx->notify_tx_done = present_ch_ctx->notify_tx_done;
+ new_ch_ctx->notify_state = present_ch_ctx->notify_state;
+ new_ch_ctx->notify_rx_intent_req = present_ch_ctx->notify_rx_intent_req;
+ new_ch_ctx->notify_rx_intent = present_ch_ctx->notify_rx_intent;
+ new_ch_ctx->notify_rx_sigs = present_ch_ctx->notify_rx_sigs;
+ new_ch_ctx->ch_open_options = present_ch_ctx->ch_open_options;
+
+// glink_os_cs_init(&new_ch_ctx->intent_q_cs);
+
+ /* close current channel */
+ present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+ if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+ /* add new channel context on negotiated xport */
+ glinki_add_ch_to_xport(new_ch_ctx->req_if_ptr,
+ new_ch_ctx->req_if_ptr,
+ new_ch_ctx,
+ &allocated_ch_ctx,
+ TRUE,
+ TRUE,
+ new_ch_ctx->req_if_ptr->glink_priority);
+ }
+#endif
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_open_ack
+
+DESCRIPTION This function is invoked by the transport in response to
+ glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ lcid Local Channel ID
+
+ prio Negotiated xport priority from remote side
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid,
+ glink_xport_priority migrated_ch_prio
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Move to closed state. Implies we clean up the channel from the
+ * open list */
+
+ /* Find channel in the open_list */
+ open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->lcid == lcid) {
+#ifndef FEATURE_CH_MIGRATION_FREE
+ glink_transport_if_type *present_if_ptr = NULL;
+ glink_channel_ctx_type *present_ch_ctx = NULL;
+ boolean channel_exist;
+ /* find the channel in all xport list */
+ channel_exist = glinki_local_channel_exists(if_ptr,
+ &present_if_ptr,
+ open_ch_ctx->name,
+ &present_ch_ctx,
+ FALSE);
+
+ if(if_ptr->glink_priority == migrated_ch_prio && !channel_exist)
+ {
+ /* only local side has opened the channel. Remote side has not come up yet
+ * which implies negotiation did not take place on remote side */
+ /* DO NOTHING */
+ }
+ else if(if_ptr->glink_priority == migrated_ch_prio)
+ {
+ /* remote channel exists. channel migration negotiation happened
+ * on remote side and negotitated xport is same as current xport */
+ if(present_ch_ctx->ref_count == 1)
+ {
+ /* remote channel is present on different xport than negotiated one.
+ * remote side will migrate its channel to negotiated xport */
+ /* DO NOTHING */
+ }
+ else if(present_ch_ctx->ref_count == 2)
+ {
+ /* remote channel is open on same xport as current xport.
+ * change channel state to GLINK_CH_STATE_OPEN and notify client */
+ open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+ open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+ GLINK_CONNECTED);
+ }
+ else
+ {
+ /* something went wrong in updating ref_count of channel */
+ ASSERT(0);
+ }
+ }
+ else
+ {
+
+ /* migrated xport priority <> current xport priority */
+ /* check if remote channel is opened on negotiated xport already */
+ if(migrated_ch_prio == present_if_ptr->glink_priority &&
+ (open_ch_ctx->ch_open_options & GLINK_OPT_INITIAL_XPORT))
+ {
+ /* remote channel is already on negotiated xport. remote channel
+ * will not migrate. Local side should migrate */
+
+ glink_channel_ctx_type *new_ch_ctx =
+ (glink_channel_ctx_type *)glink_os_calloc(
+ sizeof(glink_channel_ctx_type));
+
+ /* Fill in the channel info structure */
+ glink_os_string_copy(new_ch_ctx->name,
+ open_ch_ctx->name,
+ sizeof(open_ch_ctx->name));
+ new_ch_ctx->priv = open_ch_ctx->priv;
+ new_ch_ctx->notify_rx = open_ch_ctx->notify_rx;
+ new_ch_ctx->notify_rxv = open_ch_ctx->notify_rxv;
+ new_ch_ctx->notify_tx_done = open_ch_ctx->notify_tx_done;
+ new_ch_ctx->notify_state = open_ch_ctx->notify_state;
+ new_ch_ctx->notify_rx_intent_req =
+ open_ch_ctx->notify_rx_intent_req;
+ new_ch_ctx->notify_rx_intent = open_ch_ctx->notify_rx_intent;
+ new_ch_ctx->notify_rx_sigs = open_ch_ctx->notify_rx_sigs;
+ new_ch_ctx->ch_open_options = open_ch_ctx->ch_open_options;
+
+ present_ch_ctx->notify_state = glink_dummy_ch_migration_notification_cb;
+ if_ptr->tx_cmd_ch_close( if_ptr, present_ch_ctx->lcid );
+
+ /* migrate to negotiated xport */
+ glinki_add_ch_to_xport(present_if_ptr,
+ present_if_ptr,
+ new_ch_ctx,
+ NULL,
+ TRUE,
+ TRUE,
+ present_if_ptr->glink_priority);
+ }
+ else
+ {
+ /* Either our transport is "set in stone" OR */
+ /* remote side will migrate to negotiated xport and will call
+ * remote open on this side which will cause channel migration
+ * negotiation and this side will ultimately migrate */
+ /* DO NOTHING */
+ }
+ }
+#else
+ if(open_ch_ctx->ref_count == 2)
+ {
+ /* remote channel is open on same xport as current xport.
+ * change channel state to GLINK_CH_STATE_OPEN and notify client */
+ open_ch_ctx->state = GLINK_CH_STATE_OPEN;
+ open_ch_ctx->notify_state(open_ch_ctx, open_ch_ctx->priv,
+ GLINK_CONNECTED);
+ }
+#endif
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_OPEN_ACK, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, lcid);
+ return;
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }
+ /* We are here in case we could not find the channel in the open list. */
+ ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_close_ack
+
+DESCRIPTION This function is invoked by the transport in response to
+ glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ lcid Local Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid /* Local channel ID */
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Move to closed state. Implies we clean up the channel from the
+ * open list */
+
+ /* 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);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->lcid == lcid) {
+ /* Found channel */
+ open_ch_ctx->ref_count--;
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_CLOSE_ACK, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, lcid);
+
+ /* Transition state */
+ if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+ /* this side initiated close procedure */
+ open_ch_ctx->state = GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE;
+ } else if(open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN ||
+ open_ch_ctx->state == GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE ||
+ open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN) {
+ /* Other side never opened the port, or closed from its end */
+ /* Clear everything */
+ if(open_ch_ctx->ref_count == 0)
+ {
+ xport_ctx->channel_cleanup(open_ch_ctx);
+ /* re-use channel id if it can be done */
+ if(lcid == (xport_ctx->free_lcid-1)) {
+ /* If channel being closed is the last opened channel
+ re-use the lcid of this channel for any new channels */
+ xport_ctx->free_lcid--;
+ }
+ smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+
+ /* Notify the client */
+ open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+ GLINK_LOCAL_DISCONNECTED);
+ glink_os_free(open_ch_ctx);
+ }
+ } else {
+ /* Unsupported state */
+ ASSERT(0);
+ }
+
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+ return;
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }/* end while */
+
+ /* We are here in case we could not find the channel in the open list. */
+ ASSERT(0);
+
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_remote_close
+
+DESCRIPTION Remote channel close request; will result in sending
+ glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid /* Remote channel ID */
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ 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);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->rcid == rcid) {
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, rcid);
+ /* Found channel, transition it to appropriate state based
+ * on current state */
+ open_ch_ctx->ref_count--;
+
+ if(open_ch_ctx->state == GLINK_CH_STATE_OPEN) {
+ open_ch_ctx->state = GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE;
+
+ /* Inform the client */
+ open_ch_ctx->notify_state( open_ch_ctx, open_ch_ctx->priv,
+ GLINK_REMOTE_DISCONNECTED);
+
+ /* Send the remote close ACK back to the other side */
+ if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+ /* Free channel resources */
+ xport_ctx->channel_cleanup(open_ch_ctx);
+
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_REMOTE_CLOSE, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, rcid);
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+ return;
+ } else if (open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN ||
+ open_ch_ctx->state == GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE) {
+ /* Local side never opened the channel OR it opened it but closed it */
+ /* Free channel resources */
+ xport_ctx->channel_cleanup(open_ch_ctx);
+
+ /* Send the remote close ACK back to the other side */
+ if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+
+ if(open_ch_ctx->ref_count == 0)
+ {
+ /* re-use channel id if it can be done */
+ if (open_ch_ctx->lcid == (xport_ctx->free_lcid - 1)) {
+ /* If channel being closed is the last opened channel
+ re-use the lcid of this channel for any new channels */
+ xport_ctx->free_lcid--;
+ }
+ smem_list_delete(&if_ptr->glink_core_priv->open_list, open_ch_ctx);
+ glink_os_free(open_ch_ctx);
+ }
+
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+
+ return;
+ } else {
+ /* SHould not get this callback for a channel in any other state */
+
+ //OS_LOG_ERROR(3, "GLINK_RX_CMD_CH_REMOTE_CLOSE: received close cmd for invalid state"
+ // "[channel ctx: 0x%x][current channel state: %d]",
+ // open_ch_ctx, open_ch_ctx->state );
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+ if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, open_ch_ctx->rcid);
+ return;
+ }
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }/* end while */
+
+ /* We are here in case we could not find the channel in the open list
+ * or OPEN state. */
+ ASSERT(0);
+
+ glink_os_cs_release(&xport_ctx->channel_q_cs);
+}
+
+/*===========================================================================
+FUNCTION glink_ch_state_local_trans
+
+DESCRIPTION Process local state transition
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ glink_ch_state_type new_state /* New local channel state */
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Find channel in the open_list */
+ open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->lcid == lcid) {
+ /* Found channel, transition it to appropriate state */
+ open_ch_ctx->state = new_state;
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_STATE_TRANS, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, new_state);
+ return;
+ }/* end while */
+
+ /* We are here in case we could not find the channel in the open list
+ * or OPEN state. */
+ ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION glink_rx_put_pkt_ctx
+
+DESCRIPTION Transport invokes this call to receive a packet fragment (must
+ have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ *intent_ptr Pointer to the intent fragment
+
+ complete True if pkt is complete
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ glink_rx_intent_type *intent_ptr, /* Fragment ptr */
+ boolean complete /* True if pkt is complete */
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ glink_core_xport_ctx_type *xport_ctx;
+
+ ASSERT(if_ptr != NULL && intent_ptr != NULL);
+
+ xport_ctx = if_ptr->glink_core_priv;
+
+ /* Find channel in the open_list */
+ open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->rcid == rcid) {
+ /* Found channel */
+ GLINK_LOG_EVENT(GLINK_EVENT_CH_PUT_PKT_CTX, open_ch_ctx->name,
+ xport_ctx->xport, xport_ctx->remote_ss, intent_ptr->iid);
+
+ xport_ctx->channel_receive_pkt(open_ch_ctx, intent_ptr);
+
+ return;
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }/* end while */
+
+ /* We end up here if we don't find the channel */
+ ASSERT(0);
+}
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_remote_sigs
+
+DESCRIPTION Transport invokes this call to inform GLink of remote side
+ changing its control signals
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ remote_sigs Remote signal state.
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 remote_sigs /* Remote control signals */
+)
+{
+ glink_channel_ctx_type *open_ch_ctx;
+ uint32 prev_sigs;
+
+ ASSERT(if_ptr != NULL);
+
+ /* Find channel in the open_list */
+ open_ch_ctx = smem_list_first(&if_ptr->glink_core_priv->open_list);
+ while(open_ch_ctx != NULL)
+ {
+ if(open_ch_ctx->rcid == rcid) {
+ /* Found channel, let client know of new remote signal state */
+ prev_sigs = open_ch_ctx->remote_sigs;
+ open_ch_ctx->remote_sigs = remote_sigs;
+ open_ch_ctx->notify_rx_sigs(open_ch_ctx, open_ch_ctx->priv,
+ prev_sigs, remote_sigs);
+ return;
+ }
+ open_ch_ctx = smem_list_next(open_ch_ctx);
+ }
+
+ /* We end up here if we don't find the channel */
+ ASSERT(0);
+}
+
+
+/*===========================================================================
+FUNCTION glink_tx_resume
+
+DESCRIPTION If transport was full and could not continue a transmit
+ operation, then it will call this function to notify the core
+ that it is ready to resume transmission.
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_tx_resume
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+)
+{
+ /* Not sure what to do here */
+}
+
+
+/*===========================================================================
+FUNCTION glink_set_core_version
+
+DESCRIPTION Sets the core version used by the transport; called after
+ completing negotiation.
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Negotiated transport version
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_set_core_version
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version /* Version */
+)
+{
+}
diff --git a/platform/msm_shared/glink/glink_core_intentless_xport.c b/platform/msm_shared/glink/glink_core_intentless_xport.c
new file mode 100644
index 0000000..289ef18
--- /dev/null
+++ b/platform/msm_shared/glink/glink_core_intentless_xport.c
@@ -0,0 +1,131 @@
+/* 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.h"
+#include "glink_internal.h"
+
+/*===========================================================================
+LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ FUNCTION glink_core_stub_intentless
+===========================================================================*/
+/**
+
+ Stub for intentless transport functionality.
+
+ @return GLINK_STATUS_SUCCESS.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+
+static glink_err_type glink_core_stub_intentless(void)
+{
+ return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+ FUNCTION glink_verify_open_cfg_intentless
+===========================================================================*/
+/**
+
+ Verifies open config for an intentless transport
+
+ @param[in] open_ch_ctx Channel context.
+
+ @return TRUE if config is good.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+static boolean glink_verify_open_cfg_intentless
+(
+glink_channel_ctx_type *ch_ctx
+)
+{
+ return (ch_ctx->notify_rxv != NULL);
+}
+
+/*===========================================================================
+ FUNCTION glink_channel_receive_pkt
+===========================================================================*/
+/**
+
+ Precesses Rx packet for the channel
+
+ @param[in] open_ch_ctx Channel context.
+ @param[in] intent_ptr Packet descriptor
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+static void glink_channel_receive_pkt_intentless
+(
+ glink_channel_ctx_type *open_ch_ctx,
+ glink_rx_intent_type *intent_ptr
+)
+{
+ open_ch_ctx->notify_rxv(open_ch_ctx, open_ch_ctx->priv,
+ NULL, intent_ptr->iovec, intent_ptr->pkt_sz, 0,
+ intent_ptr->vprovider, intent_ptr->pprovider);
+}
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ FUNCTION glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+ Initializes internal core functions for the intentless transport.
+
+ @param[in] if_ptr The Pointer to the interface instance.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr)
+{
+ if_ptr->glink_core_priv->verify_open_cfg = glink_verify_open_cfg_intentless;
+ if_ptr->glink_core_priv->channel_init = (channel_init_fn)glink_core_stub_intentless;
+ if_ptr->glink_core_priv->channel_cleanup = (channel_cleanup_fn)glink_core_stub_intentless;
+ if_ptr->glink_core_priv->use_rm_intent = (use_rm_intent_fn)glink_core_stub_intentless;
+ if_ptr->glink_core_priv->channel_receive_pkt = glink_channel_receive_pkt_intentless;
+}
diff --git a/platform/msm_shared/glink/glink_os_utils_dal.c b/platform/msm_shared/glink/glink_os_utils_dal.c
new file mode 100644
index 0000000..7ad6fb7
--- /dev/null
+++ b/platform/msm_shared/glink/glink_os_utils_dal.c
@@ -0,0 +1,358 @@
+/* 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_os_utils.h"
+#include <arch/defines.h>
+#include <malloc.h>
+#include <kernel/thread.h>
+#include <string.h>
+#include <kernel/event.h>
+#include <platform/irqs.h>
+#include <platform/interrupts.h>
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_BUFFER_SIZE ( 16384 )
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+typedef void (*glink_os_thread_fn_type)(void* param);
+
+typedef struct _glink_os_thread_info_type {
+ glink_os_thread_fn_type thread_fn;
+ void *param;
+}glink_os_thread_info_type;
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ FUNCTION glink_os_cs_init
+===========================================================================*/
+/**
+ Initializes a Critical Section
+
+ @param[in] cs pointer to critical section object allocated by caller.
+
+ @return
+ TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+boolean glink_os_cs_init( os_cs_type *cs )
+{
+ boolean return_value = TRUE;
+
+ /* Create the new critical section */
+
+ return ( return_value );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_cs_deinit
+===========================================================================*/
+/**
+ This function de-initializes a critical section.
+
+ @param[in] cs Pointer to the critical section to be de-initialized.
+
+ @return
+ TRUE if critical section was initialized, FALSE otherwise
+
+*/
+/*=========================================================================*/
+boolean glink_os_cs_deinit( os_cs_type *cs )
+{
+ /* Deinitialize the critical section */
+
+ return TRUE;
+}
+
+/*===========================================================================
+FUNCTION glink_os_cs_acquire
+===========================================================================*/
+/**
+ Lock a critical section
+
+ @param[in] cs Pointer the the critical section
+
+ @return None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs )
+{
+ enter_critical_section();
+}
+
+/*===========================================================================
+FUNCTION glink_os_cs_release
+===========================================================================*/
+/**
+ Unlock a critical section
+
+ @param[in] cs Pointer the the critical section
+
+ @return None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs )
+{
+ exit_critical_section();
+}
+
+/*===========================================================================
+FUNCTION glink_os_cs_destroy
+===========================================================================*/
+/**
+ Destroys a Critical Section
+
+ @return none.
+*/
+/*=========================================================================*/
+void glink_os_cs_destroy( os_cs_type *cs )
+{
+ /* Initialize the critical section */
+ return;
+}
+
+/*===========================================================================
+ FUNCTION glink_os_malloc
+===========================================================================*/
+/**
+ Dynamically allocate a region of memory from the heap. The region should be
+ freed using \c glink_os_free when no longer used.
+
+ @param[in] size The number of bytes to be allocated.
+
+ @return The pointer to the region of memory that was allocated.
+ NULL if the allocation failed.
+*/
+/*=========================================================================*/
+
+void *glink_os_malloc( size_t size )
+{
+ void *pMem;
+
+ pMem = malloc(size);
+ if (pMem == NULL)
+ return NULL;
+ return pMem;
+}
+
+/*===========================================================================
+ FUNCTION glink_os_calloc
+===========================================================================*/
+/**
+ Dynamically allocate a region of memory from the heap and initialize with
+ the zeroes. The region should be freed using \c glink_os_free
+ when no longer used.
+
+ @param[in] size The number of bytes to be allocated.
+
+ @return The pointer to the region of memory that was allocated.
+ NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size )
+{
+ void *pMem;
+ pMem = malloc(size);
+ if( pMem == NULL )
+ {
+ return NULL;
+ }
+ else
+ {
+ memset( pMem, 0, size );
+ return pMem;
+ }
+}
+
+/*===========================================================================
+ FUNCTION glink_os_free
+===========================================================================*/
+/**
+ Free a region of memory that was allocated by \c glink_os_malloc.
+
+ @param[in] pMem The reference to the region of memory to be freed.
+
+ @return NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem )
+{
+ free( pMem );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_string_copy
+===========================================================================*/
+/**
+ Copies the source string into the destination buffer until
+ size is reached, or until a '\0' is encountered. If valid,
+ the destination string will always be NULL deliminated.
+
+ @param[in] dst The destination string, contents will be updated.
+ @param[in] src The source string
+ @param[in] size The maximum copy size (size of dst)
+
+ @return
+ The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy( char *dst, const char *src, uint32 size )
+{
+ ( void )strlcpy( dst, src, size );
+
+ return dst;
+}
+
+/*===========================================================================
+ FUNCTION glink_os_string_compare
+===========================================================================*/
+/**
+ Compares two strings delimited by size or NULL character.
+
+ @param[in] s1 String 1
+ @param[in] s2 String 2
+ @param[in] size The maximum number of characters to compare
+
+ @return
+ 0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32 size )
+{
+ return strncmp( s1, s2, size );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_copy_mem
+===========================================================================*/
+/**
+ Copies the source buffer into the destination buffer.
+
+ @param[in] dst The destination, contents will be updated.
+ @param[in] src The source
+ @param[in] size The maximum copy size (size of dst)
+
+ @return
+ The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem( void *dst, const void *src, uint32 size )
+{
+ memcpy( dst, src, size );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_register_isr
+===========================================================================*/
+/**
+ Registers ISR with the interrupt controller
+
+ @param[in] irq_in Interrupt to register for
+ @param[in] isr Callback to be invoked when interrupt fires
+ @param[in] cb_data Data to be provided to the callback
+
+ @return TRUE if registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_register_isr( uint32 irq_in, os_isr_cb_fn isr, void* cb_data )
+{
+ boolean return_value = TRUE;
+
+ /* Register the interrupt */
+ dprintf(SPEW, "Register interrupt: %u\n", irq_in);
+ register_int_handler(irq_in, (int_handler)(isr), cb_data);
+
+ return ( return_value );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_deregister_isr
+===========================================================================*/
+/**
+ De-registers ISR with the interrupt controller
+
+ @param[in] irq_in Interrupt to deregister for
+
+ @return TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_deregister_isr( uint32 irq_in )
+{
+ boolean return_value = TRUE;
+ mask_interrupt(irq_in);
+ return ( return_value );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_enable_interrupt
+===========================================================================*/
+/**
+ Enables the interrupt in the interrupt controller
+
+ @param[in] irq_in Interrupt to enable
+
+ @return TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_enable_interrupt( uint32 irq_in )
+{
+ boolean return_value = TRUE;
+ unmask_interrupt(irq_in);
+ return ( return_value );
+}
+
+/*===========================================================================
+ FUNCTION glink_os_disable_interrupt
+===========================================================================*/
+/**
+ Disables the interrupt in the interrupt controller
+
+ @param[in] irq_in Interrupt to disable
+
+ @return TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+boolean glink_os_disable_interrupt( uint32 irq_in )
+{
+ boolean return_value = TRUE;
+ dprintf(INFO, "Disable IPC Interrupt\n");
+ mask_interrupt(irq_in);
+ return ( return_value );
+}
diff --git a/platform/msm_shared/glink/glink_rpmcore_setup.c b/platform/msm_shared/glink/glink_rpmcore_setup.c
new file mode 100644
index 0000000..a206afa
--- /dev/null
+++ b/platform/msm_shared/glink/glink_rpmcore_setup.c
@@ -0,0 +1,65 @@
+/* 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.h"
+#include "glink_internal.h"
+
+
+/*===========================================================================
+EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION glink_core_setup
+===========================================================================*/
+/**
+
+ Initializes internal core functions based on the transport capabilities.
+
+ @param[in] if_ptr The Pointer to the interface instance.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr)
+{
+ if (if_ptr->glink_core_priv->xport_capabilities & GLINK_CAPABILITY_INTENTLESS)
+ {
+ glink_core_setup_intentless_xport(if_ptr);
+ }
+ else
+ {
+ ASSERT(0);
+ }
+}
diff --git a/platform/msm_shared/glink/glink_vector.c b/platform/msm_shared/glink/glink_vector.c
new file mode 100644
index 0000000..31f0883
--- /dev/null
+++ b/platform/msm_shared/glink/glink_vector.c
@@ -0,0 +1,196 @@
+/* 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.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_vector.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+ LOCAL DATA DECLARATIONS
+===========================================================================*/
+
+
+/*===========================================================================
+ PRIVATE FUNCTIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+ Buffer provider for virtual space that operates on a non-vectored buffer.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return virtual address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+)
+{
+ glink_core_tx_pkt_type* pkt = (glink_core_tx_pkt_type*)iovec;
+
+ if (pkt == NULL || size == NULL || pkt->size <= offset)
+ {
+ return NULL;
+ }
+
+ *size = pkt->size - offset;
+
+ return (char*)(pkt->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION glink_iovec_vprovider
+===========================================================================*/
+/**
+
+ Buffer provider for virtual space that operates on a Glink iovec.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return virtual address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+)
+{
+ glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+ if (iovec_l == NULL || size == NULL)
+ {
+ return NULL;
+ }
+
+ if (!iovec_l->vlist)
+ {
+ // create vlist and map virtual from physical addresses
+ ASSERT(0);
+ }
+
+ if (!iovec_l->vlast || iovec_l->vlast->start_offset > offset)
+ {
+ iovec_l->vlast = iovec_l->vlist;
+ }
+
+ while (iovec_l->vlast &&
+ iovec_l->vlast->start_offset + iovec_l->vlast->size <= offset)
+ {
+ iovec_l->vlast = iovec_l->vlast->next;
+ }
+
+ if (iovec_l->vlast == NULL)
+ {
+ return NULL;
+ }
+
+ offset -= iovec_l->vlast->start_offset;
+ *size = iovec_l->vlast->size - offset;
+
+ return (char*)(iovec_l->vlast->data) + offset;
+}
+
+/*===========================================================================
+FUNCTION glink_iovec_pprovider
+===========================================================================*/
+/**
+
+ Buffer provider for physical space that operates on a Glink iovec.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return physical address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+)
+{
+ glink_iovector_type* iovec_l = (glink_iovector_type*)iovec;
+
+ if (iovec_l == NULL || size == NULL)
+ {
+ return NULL;
+ }
+
+ if (!iovec_l->plist)
+ {
+ // create plist and get physical addresses from virtual
+ ASSERT(0); // not implemented
+ }
+
+ if (!iovec_l->plast || iovec_l->plast->start_offset > offset)
+ {
+ iovec_l->plast = iovec_l->plist;
+ }
+
+ while (iovec_l->plast &&
+ iovec_l->plast->start_offset + iovec_l->plast->size <= offset)
+ {
+ iovec_l->plast = iovec_l->plast->next;
+ }
+
+ if (iovec_l->plast == NULL)
+ {
+ return NULL;
+ }
+
+ offset -= iovec_l->plast->start_offset;
+ *size = iovec_l->plast->size - offset;
+
+ return (char*)(iovec_l->plast->data) + offset;
+}
diff --git a/platform/msm_shared/glink/xport_rpm.c b/platform/msm_shared/glink/xport_rpm.c
new file mode 100644
index 0000000..f1b68b9
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm.c
@@ -0,0 +1,1150 @@
+/* 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.h"
+#include "glink_core_if.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+#include "glink_internal.h"
+#include "glink_vector.h"
+#include "xport_rpm_config.h"
+#include "xport_rpm.h"
+#include <reg.h>
+#include <bits.h>
+#include <platform/iomap.h>
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+#define XPORT_RPM_NAME "RPM"
+
+#define XPORT_RPM_LOG(msg, remote_host, param) \
+ GLINK_LOG_EVENT(GLINK_EVENT_XPORT_INTERNAL, msg, XPORT_RPM_NAME, \
+ remote_host, (uint32)param)
+
+#define MSGRAM_READ32(ctx, ind) (*(volatile uint32*)&(ctx)->rx_fifo[ind])
+#define CHECK_INDEX_WRAP_AROUND(ind, size) \
+ {if ((ind) >= (size)) ind = 0;}
+
+#define ROUNDUP64(d) (((d) + 7) & (~7))
+#define ROUNDUP32(d) (((d) + 3) & (~3))
+
+/*===========================================================================
+ GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+extern const uint32 xport_rpm_config_num;
+extern const char* xport_rpm_msg_ram;
+extern const void* xport_rpm_msg_ram_toc;
+
+xport_rpm_config_type* xport_rpm_get_config(uint32 ind);
+
+/* RPM channel descriptor */
+typedef struct _xport_rpm_ind_type
+{
+ uint32 read_ind;
+ uint32 write_ind;
+} xport_rpm_ind_type;
+
+/* RPM transport context */
+typedef struct _xport_rpm_ctx_type
+{
+ /* context structure should start from trasport interface */
+ glink_transport_if_type xport_if;
+ const xport_rpm_config_type *pcfg;
+ volatile xport_rpm_ind_type* tx_desc;
+ volatile xport_rpm_ind_type* rx_desc;
+ char* tx_fifo;
+ char* rx_fifo;
+ uint32 tx_fifo_size;
+ uint32 rx_fifo_size;
+ os_cs_type *tx_link_lock;
+ os_cs_type *rx_link_lock;
+ uint32 pkt_start_ind;
+ uint32 pkt_size;
+ boolean reset;
+ boolean irq_mask;
+} xport_rpm_ctx_type;
+
+xport_rpm_ctx_type *xport_rpm_ctx = NULL;
+glink_core_version_type xport_rpm_version;
+
+/*===========================================================================
+ LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION xport_rpm_plain_pkt_provider
+===========================================================================*/
+/**
+
+ Packet provider for virtual space that operates on MSG RAM FIFO.
+
+ @param[in] iovec Pointer to the vector.
+ @param[in] offset Offset within the vector.
+ @param[out] size Size of the provied buffer.
+
+ @return virtual address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+static void* xport_rpm_pkt_provider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+)
+{
+ xport_rpm_ctx_type* ctx_ptr = (xport_rpm_ctx_type*)iovec;
+ uint32 last;
+
+ if (ctx_ptr == NULL || size == NULL || ctx_ptr->pkt_size <= offset)
+ {
+ return NULL;
+ }
+
+ last = ctx_ptr->rx_fifo_size - ctx_ptr->pkt_start_ind;
+
+ if (offset >= last)
+ {
+ *size = ctx_ptr->pkt_size - offset;
+
+ return &ctx_ptr->rx_fifo[offset - last];
+ }
+
+ *size = ctx_ptr->pkt_size <= last ?
+ ctx_ptr->pkt_size - offset :
+ last - offset;
+
+ return &ctx_ptr->rx_fifo[offset + ctx_ptr->pkt_start_ind];
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_send_event
+===========================================================================*/
+/**
+
+ Updates shared write index and sends interrupt.
+
+ @param[in] ctx_ptr Pointer to transport context.
+
+ @return None.
+
+ @sideeffects None.
+
+ @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static void xport_rpm_send_event
+(
+ xport_rpm_ctx_type *ctx_ptr
+)
+{
+ /* read out the write index to initiate a bus transaction from MSG RAM */
+ volatile uint32 write_ind = ctx_ptr->tx_desc->write_ind;
+
+ XPORT_RPM_LOG("Send event write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+
+ // notify rpm
+ dprintf(SPEW, "%s:%d: Notify RPM with IPC interrupt\n", __func__, __LINE__);
+ /* Set BIT 0 to notify RPM via IPC interrupt*/
+ writel(BIT(0), APCS_HLOS_IPC_INTERRUPT_0);
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_write_msgram
+===========================================================================*/
+/**
+
+ Copies data from local buffer into Tx FIFO located at MSG RAM
+
+ @param[in] ctx_ptr Pointer to transport context.
+ @param[in] write_ind Index to start wrting from.
+ @param[in] buffer Buffer to copy from.
+ @param[in] size Size of the data in the buffer.
+
+ @return New write index.
+
+ @sideeffects None.
+
+ @dependencies It should be invoked within tx_link_lock protection.
+*/
+/*=========================================================================*/
+static uint32 xport_rpm_write_msgram
+(
+ xport_rpm_ctx_type *ctx_ptr,
+ uint32 write_ind,
+ uint32 *buffer,
+ uint32 size
+)
+{
+ uint32 remaining = ctx_ptr->tx_fifo_size - write_ind;
+ uint32 *buffer_end;
+ volatile uint32* write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[write_ind];
+
+ if (remaining <= size)
+ {
+ buffer_end = (uint32*)((char*)buffer + remaining);
+
+ /* write in 32bit increments due to MSG RAM access requirement */
+ while (buffer < buffer_end)
+ {
+ *write_ptr++ = *buffer++;
+ }
+
+ size -= remaining;
+ write_ptr = (volatile uint32*)&ctx_ptr->tx_fifo[0];
+ }
+
+ buffer_end = (uint32*)((char*)buffer + size);
+
+ /* write in 32bit increments due to MSG RAM access requirement */
+ while (buffer < buffer_end)
+ {
+ *write_ptr++ = *buffer++;
+ }
+
+ return (char*)write_ptr - &ctx_ptr->tx_fifo[0];
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_send_cmd
+===========================================================================*/
+/**
+
+ Helper to send a single command.
+
+ @param[in] ctx_ptr Pointer to transport context.
+ @param[in] cmd buffer containing the command
+ @param[in] cmd_size Size of command buffer.
+ @param[in] data buffer containing the data
+ @param[in] data_size Size of data buffer.
+
+ @return None.
+
+ @dependencies None.
+*/
+/*=========================================================================*/
+static glink_err_type xport_rpm_send_cmd
+(
+ xport_rpm_ctx_type *ctx_ptr,
+ uint32 *cmd,
+ uint32 cmd_size,
+ uint32 *data,
+ uint32 data_size
+)
+{
+ uint32 total_size = cmd_size + data_size;
+ uint32 reserve_size = ROUNDUP64(total_size);
+ uint32 write_ind, read_ind, avail_size;
+
+ glink_os_cs_acquire(ctx_ptr->tx_link_lock);
+
+ write_ind = ctx_ptr->tx_desc->write_ind;
+ read_ind = ctx_ptr->tx_desc->read_ind;
+ avail_size = write_ind < read_ind ? read_ind - write_ind :
+ ctx_ptr->tx_fifo_size - write_ind + read_ind;
+
+ if (reserve_size + sizeof(uint64_t) > avail_size)
+ {
+ glink_os_cs_release(ctx_ptr->tx_link_lock);
+ return GLINK_STATUS_OUT_OF_RESOURCES;
+ }
+
+ XPORT_RPM_LOG("send cmd", ctx_ptr->pcfg->remote_ss, cmd[0]);
+
+ write_ind
+ = xport_rpm_write_msgram( ctx_ptr, write_ind,
+ cmd, ROUNDUP32( cmd_size ) );
+
+ if (data != NULL)
+ {
+ write_ind
+ = xport_rpm_write_msgram( ctx_ptr, write_ind,
+ data, ROUNDUP32( data_size ) );
+ }
+
+ /* add alignment bytes to Tx FIFO */
+ write_ind += (reserve_size - total_size) & (~3);
+
+ if (write_ind >= ctx_ptr->tx_fifo_size)
+ {
+ write_ind -= ctx_ptr->tx_fifo_size;
+ }
+
+ ctx_ptr->tx_desc->write_ind = write_ind;
+
+ xport_rpm_send_event(ctx_ptr);
+
+ glink_os_cs_release(ctx_ptr->tx_link_lock);
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_version
+===========================================================================*/
+/**
+
+ Transmit a version command for local negotiation -
+ expected response is to be delivered via glink_rx_cmd_version_ack().
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] version Version to be sent.
+ @param[in] feature Features to be sent.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd[2];
+
+ cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_REQ);
+ cmd[0] |= XPORT_RPM_SET_VERSION(version);
+ cmd[1] = features;
+
+ if(xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+ {
+ dprintf(CRITICAL, "%s:%d: Send Version Failed\n", __func__, __LINE__);
+ ASSERT(0);
+ }
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_version_ack
+===========================================================================*/
+/**
+
+ Transmit a version ack for remote negotiation.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] version Version to be sent.
+ @param[in] feature Features to be sent.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_version_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd[2];
+
+ cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_VERSION_ACK);
+ cmd[0] |= XPORT_RPM_SET_VERSION(version);
+ cmd[1] = features;
+
+ if (xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+ {
+ dprintf(CRITICAL, "%s:%d: Send Version ACK Failed", __func__, __LINE__);
+ ASSERT(0);
+ }
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_set_version
+===========================================================================*/
+/**
+
+ Signals that negotiation is complete and the transport can now
+ do version-specific initialization.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] version Version to be used.
+ @param[in] feature Features to be used.
+
+ @return Capabilities.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_set_version
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+)
+{
+ return GLINK_CAPABILITY_SIG_SUPPORT | GLINK_CAPABILITY_INTENTLESS;
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_ch_open
+===========================================================================*/
+/**
+
+ Sends the open command - expected response is to be delivered
+ via glink_rx_cmd_ch_open_ack().
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] lcid Local channel ID.
+ @param[in] name Channel name.
+ @param[in] prio Requested xport priority by channel.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_open
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid,
+ const char *name,
+ glink_xport_priority prio
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd[2];
+
+ cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL);
+ cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+ cmd[1] = strlen(name) + 1;
+
+ return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)name, cmd[1]);
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_ch_close
+===========================================================================*/
+/**
+
+ Sends the close command - expected response is to be delivered
+ via glink_rx_cmd_ch_close_ack().
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] lcid Local channel ID.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_ch_close
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd;
+
+ cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL);
+ cmd |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+
+ return xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_ch_remote_open_ack
+===========================================================================*/
+/**
+
+ Sends the remote open ACK command.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] rcid Remote channel ID.
+ @param[in] prio send negotiated xport priority to remote side.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_open_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 rcid,
+ glink_xport_priority prio
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd;
+
+ cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_OPEN_CHANNEL_ACK);
+ cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+ if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+ {
+ //ERR_FATAL("send Open Ack failed", 0, 0, 0);
+ ASSERT(0);
+ }
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_ch_remote_close_ack
+===========================================================================*/
+/**
+
+ Sends the remote close ACK command.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] rcid Remote channel ID.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void xport_rpm_tx_cmd_ch_remote_close_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 rcid
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd;
+
+ cmd = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_CLOSE_CHANNEL_ACK);
+ cmd |= XPORT_RPM_SET_CHANNEL_ID(rcid);
+
+ if (xport_rpm_send_cmd(ctx_ptr, &cmd, sizeof(cmd), NULL, 0) != GLINK_STATUS_SUCCESS)
+ {
+ dprintf(CRITICAL, "%s:%d: Send Clock ACK failed\n", __func__, __LINE__);
+ ASSERT(0);
+ }
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx
+===========================================================================*/
+/**
+
+ Send a data packet or a fragment of it.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] lcid Local channel ID.
+ @param[in] pctx Packet TX context.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid,
+ glink_core_tx_pkt_type *pctx
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd[4];
+
+ cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_DATA);
+ cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+ cmd[1] = 0;
+ cmd[2] = pctx->size;
+ cmd[3] = 0;
+
+ pctx->size_remaining = 0;
+
+ return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), (void*)pctx->data, pctx->size);
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_tx_cmd_set_sigs
+===========================================================================*/
+/**
+
+ Sends the local channel signals as per the specified 32-bit mask.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] lcid Local channel ID.
+ @param[in] sigs Signal mask.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_tx_cmd_set_sigs
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid,
+ uint32 sigs
+)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+ uint32 cmd[2];
+
+ cmd[0] = XPORT_RPM_SET_CMD_ID(XPORT_RPM_CMD_TX_SIGNALS);
+ cmd[0] |= XPORT_RPM_SET_CHANNEL_ID(lcid);
+ cmd[1] = sigs;
+
+ return xport_rpm_send_cmd(ctx_ptr, &cmd[0], sizeof(cmd), NULL, 0);
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_negotiate_features
+===========================================================================*/
+/**
+
+ Callback to verify feature set.
+
+ @param[in] if_ptr Pointer to transport interface.
+ @param[in] version_ptr Pointer to version descriptor.
+ @param[in] features Proposed feature set.
+
+ @return 0.
+
+ @sideeffects None.
+
+ @dependencies None.
+*/
+/*=========================================================================*/
+uint32 xport_rpm_negotiate_features(
+ glink_transport_if_type *if_ptr,
+ const glink_core_version_type *version_ptr,
+ uint32 features)
+{
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_poll
+===========================================================================*/
+/**
+
+ Poll of RPM transport.
+
+ @param[in] ctx_ptr Pointer to transport context.
+
+ @return Returns error code.
+
+ @sideeffects None.
+
+ @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_poll( xport_rpm_ctx_type *ctx_ptr )
+{
+ uint32 write_ind, read_ind;
+ boolean stop_processing = FALSE;
+
+ if (ctx_ptr->reset == TRUE)
+ {
+ /* reset flag has been set after SSR, notify link up */
+ ctx_ptr->reset = FALSE;
+ ctx_ptr->xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)ctx_ptr);
+ }
+
+ glink_os_cs_acquire(ctx_ptr->rx_link_lock);
+
+ /* Process pending commands and data */
+ write_ind = ctx_ptr->rx_desc->write_ind;
+ read_ind = ctx_ptr->rx_desc->read_ind;
+
+ XPORT_RPM_LOG("RPM ISR write ind", ctx_ptr->pcfg->remote_ss, write_ind);
+ XPORT_RPM_LOG("RPM ISR read ind", ctx_ptr->pcfg->remote_ss, read_ind);
+
+ /* Ensure the index is 64-bit aligned */
+ if ((write_ind & 0x7) != 0)
+ {
+ dprintf(CRITICAL,"%s:%d: Write Index is not aligned: %u\n",__func__, __LINE__, write_ind);
+ ASSERT(0);
+ }
+
+ while (write_ind != read_ind && !stop_processing)
+ {
+ uint32 cmd = MSGRAM_READ32(ctx_ptr, read_ind);
+ uint32 cid = XPORT_RPM_GET_CHANNEL_ID(cmd); // most commands have channel ID
+ uint32 cmd_arg;
+
+ /* it can't wrap aroud here so just inceremt the index */
+ read_ind += sizeof(cmd);
+
+ XPORT_RPM_LOG("Cmd Rx", ctx_ptr->pcfg->remote_ss, cmd);
+
+ switch (XPORT_RPM_GET_CMD_ID(cmd))
+ {
+ case XPORT_RPM_CMD_VERSION_REQ:
+
+ cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+ /* no need to incerment read_ind here since it will be rounded up */
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version(
+ (glink_transport_if_type *)ctx_ptr,
+ XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+ break;
+
+ case XPORT_RPM_CMD_VERSION_ACK:
+
+ cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+ /* no need to increment read_ind here since it will be rounded up */
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_version_ack(
+ (glink_transport_if_type *)ctx_ptr,
+ XPORT_RPM_GET_VERSION(cmd), cmd_arg);
+ break;
+
+ case XPORT_RPM_CMD_OPEN_CHANNEL:
+ cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+ cmd_arg = ROUNDUP64(cmd_arg);
+
+ read_ind += sizeof(cmd_arg);
+
+ /* channel name should fit into the FIFO */
+ if (cmd_arg == 0 || cmd_arg >= ctx_ptr->rx_fifo_size)
+ {
+ dprintf(CRITICAL, "%s:%d: Invalid name length: %u", __func__, __LINE__, cmd_arg);
+ ASSERT(0);
+ }
+ else
+ {
+ char tmpstr[ROUNDUP64(GLINK_CH_NAME_LEN)];
+ uint32 curr = 0;
+
+ while (curr < cmd_arg && curr < sizeof(tmpstr))
+ {
+ CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+ *(uint32*)&tmpstr[curr] = MSGRAM_READ32(ctx_ptr, read_ind);
+ curr += sizeof(uint32);
+ read_ind += sizeof(uint32);
+ }
+
+ /* add all the unread stuff */
+ read_ind += cmd_arg - curr;
+
+ /* make sure the last character is NULL */
+ tmpstr[sizeof(tmpstr) - 1] = 0;
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+ (glink_transport_if_type *)ctx_ptr, cid, tmpstr, GLINK_XPORT_RPM);
+ }
+
+ break;
+
+ case XPORT_RPM_CMD_CLOSE_CHANNEL:
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_remote_close(
+ //(glink_transport_if_type *)ctx_ptr, XPORT_RPM_GET_CHANNEL_ID(cmd));
+ (glink_transport_if_type *)ctx_ptr, cid);
+
+ /* no need to increment read_ind here since it would be rounded up */
+
+ break;
+
+ case XPORT_RPM_CMD_OPEN_CHANNEL_ACK:
+
+ /* no need to increment read_ind here since it would be rounded up */
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+ (glink_transport_if_type *)ctx_ptr, cid, GLINK_XPORT_RPM);
+
+ break;
+
+ case XPORT_RPM_CMD_CLOSE_CHANNEL_ACK:
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+ (glink_transport_if_type *)ctx_ptr, cid);
+
+ /* no need to increment read_ind here since it would be rounded up */
+
+ break;
+
+ case XPORT_RPM_CMD_TX_DATA:
+ {
+ glink_rx_intent_type desc;
+ memset( &desc, sizeof( glink_rx_intent_type), 0 );
+
+ read_ind += sizeof(cmd_arg);
+
+ CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+ cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+ /* packet data should fit into the FIFO */
+ if (cmd_arg >= ctx_ptr->rx_fifo_size)
+ {
+ dprintf(CRITICAL, "%s:%d: Invalid packet length: %u",__func__, __LINE__, cmd_arg);
+ ASSERT(0);
+ }
+
+ read_ind += 2*sizeof(cmd_arg);
+
+ CHECK_INDEX_WRAP_AROUND(read_ind, ctx_ptr->rx_fifo_size);
+
+ ctx_ptr->pkt_start_ind = read_ind;
+ ctx_ptr->pkt_size = cmd_arg;
+
+ desc.size = cmd_arg;
+ desc.used = cmd_arg;
+ desc.pkt_sz = cmd_arg;
+ desc.iovec = ctx_ptr;
+ desc.vprovider = xport_rpm_pkt_provider;
+
+ read_ind += cmd_arg;
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_put_pkt_ctx(
+ (glink_transport_if_type *)ctx_ptr, cid,
+ &desc, TRUE);
+
+ /* If interrupt was disabled then stop delivering messages */
+ stop_processing = ctx_ptr->irq_mask;
+
+ break;
+ }
+
+ case XPORT_RPM_CMD_TX_SIGNALS:
+
+ cmd_arg = MSGRAM_READ32(ctx_ptr, read_ind);
+
+ /* no need to incerement read_ind here since it will be rounded up */
+
+ ctx_ptr->xport_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+ (glink_transport_if_type *)ctx_ptr,
+ cid, cmd_arg);
+ break;
+
+ default:
+ dprintf(CRITICAL, "%s:%d: Invalid Command: %u\n",__func__, __LINE__, cmd);
+ ASSERT(0);
+ break;
+ }
+
+ read_ind = ROUNDUP64(read_ind);
+
+ if (read_ind >= ctx_ptr->rx_fifo_size)
+ {
+ read_ind -= ctx_ptr->rx_fifo_size;
+ }
+
+ /* Update the shared read index */
+ ctx_ptr->rx_desc->read_ind = read_ind;
+ }
+
+ glink_os_cs_release(ctx_ptr->rx_link_lock);
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+#ifdef GLINK_RPM_PROC
+/*===========================================================================
+FUNCTION xport_rpm_isr
+===========================================================================*/
+/**
+
+ ISR of RPM transport.
+
+ @return Returns error code.
+
+ @sideeffects None.
+
+ @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( void )
+{
+ xport_rpm_ctx_type *ctx_ptr = xport_rpm_get_context();
+
+ return xport_rpm_poll( ctx_ptr );
+}
+#else
+/*===========================================================================
+FUNCTION xport_rpm_isr
+===========================================================================*/
+/**
+
+ ISR of RPM transport.
+
+ @param[in] ctx_ptr Pointer to transport context.
+
+ @return Returns error code.
+
+ @sideeffects None.
+
+ @dependencies None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_isr( xport_rpm_ctx_type *ctx_ptr )
+{
+ return xport_rpm_poll( ctx_ptr );
+}
+#endif
+
+
+/*===========================================================================
+FUNCTION xport_rpm_ssr
+===========================================================================*/
+/**
+
+ Processes SSR event.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_ssr(glink_transport_if_type *if_ptr)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+ ctx_ptr->tx_desc->write_ind = 0;
+ ctx_ptr->rx_desc->read_ind = 0;
+ ctx_ptr->reset = TRUE;
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_wait_link_down
+===========================================================================*/
+/**
+
+ Waits for read/write indicies to be set to 0 by the remote host.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+
+ @return TRUE if link is down, FALSE otherwise.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+boolean xport_rpm_wait_link_down(glink_transport_if_type *if_ptr)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+ return (ctx_ptr->tx_desc->write_ind == 0 &&
+ ctx_ptr->tx_desc->read_ind == 0 &&
+ ctx_ptr->rx_desc->write_ind == 0 &&
+ ctx_ptr->rx_desc->read_ind == 0);
+}
+
+
+/*===========================================================================
+FUNCTION xport_rpm_mask_interrupt
+===========================================================================*/
+/**
+
+ Enables or disables interrupts.
+
+ @param[in] if_ptr Pointer to transport interface instance.
+ @param[in] mask TRUE=mask, FALSE=unmask
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_mask_interrupt(glink_transport_if_type *if_ptr, boolean mask)
+{
+ xport_rpm_ctx_type *ctx_ptr = (xport_rpm_ctx_type *)if_ptr;
+
+ if (ctx_ptr->irq_mask != mask)
+ {
+ if (mask)
+ {
+ glink_os_disable_interrupt(ctx_ptr->pcfg->irq_in);
+ }
+ else
+ {
+ glink_os_enable_interrupt(ctx_ptr->pcfg->irq_in);
+ }
+
+ ctx_ptr->irq_mask = mask;
+ }
+
+ return GLINK_STATUS_SUCCESS;
+}
+
+/*===========================================================================
+FUNCTION xport_rpm_init
+===========================================================================*/
+/**
+
+ Initializes RPM transport.
+ Must be called before any other operations are done.
+
+ @param[in] arg The argument.
+
+ @return Returns error code.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+glink_err_type xport_rpm_init(void *arg)
+{
+ uint32 ind;
+ glink_core_transport_cfg_type xport_rpm_cfg = { 0 };
+ uint32 *msg_ram_toc = (uint32*)xport_rpm_msg_ram_toc;
+ xport_rpm_toc_entry_type *entry;
+ uint32 msg_ram_toc_num;
+ char* msg_ram_toc_entry_start = (char*)&msg_ram_toc[XPORT_RPM_TOC_ENTRIES_IDX];
+ dprintf(SPEW, "%s:%d: RPM Transport INIT\n", __func__, __LINE__);
+
+ if (xport_rpm_config_num == 0)
+ {
+ return GLINK_STATUS_SUCCESS;
+ }
+
+ if (msg_ram_toc[XPORT_RPM_TOC_MAGIC_IDX] != XPORT_RPM_TOC_MAGIC)
+ {
+ dprintf(CRITICAL, "%s:%d: RPM Transport Failure: Invalid ToC cookie\n", __func__, __LINE__);
+ return GLINK_STATUS_FAILURE;
+ }
+
+ msg_ram_toc_num = msg_ram_toc[XPORT_RPM_TOC_LENGTH_IDX];
+
+ if (msg_ram_toc_num == 0)
+ {
+ dprintf(SPEW, "%s:%d RPM Transport Success\n", __func__, __LINE__);
+ return GLINK_STATUS_SUCCESS;
+ }
+
+ xport_rpm_ctx = glink_os_calloc(sizeof(*xport_rpm_ctx)*xport_rpm_config_num);
+
+ if (xport_rpm_ctx == NULL)
+ {
+ dprintf(INFO, "%s:%d RPM Transport Failed to allocate context\n", __func__, __LINE__);
+ ASSERT(0);
+ }
+
+ /* Initialize supported version and features */
+ xport_rpm_version.version = 1;
+ xport_rpm_version.features = 0;
+ xport_rpm_version.negotiate_features = &xport_rpm_negotiate_features;
+
+ /* Initialize edges */
+ dprintf(SPEW, "%s:%d: Initialize Edges\n", __func__, __LINE__);
+
+ for (ind = 0; ind < xport_rpm_config_num; ind++)
+ {
+ xport_rpm_ctx[ind].pcfg = xport_rpm_get_config(ind);
+
+ /* Find FIFOs in MSG RAM ToC */
+ for (entry = (xport_rpm_toc_entry_type*)msg_ram_toc_entry_start;
+ (char*)entry < msg_ram_toc_num*sizeof(*entry) + msg_ram_toc_entry_start &&
+ (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL);
+ entry++)
+ {
+ if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->tx_fifo_id)
+ {
+ xport_rpm_ctx[ind].tx_desc = (xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+ xport_rpm_ctx[ind].tx_desc->write_ind = 0;
+ xport_rpm_ctx[ind].tx_fifo = (char*)(xport_rpm_ctx[ind].tx_desc + 1);
+ xport_rpm_ctx[ind].tx_fifo_size = entry->fifo_size;
+ }
+ else if (entry->fifo_id == xport_rpm_ctx[ind].pcfg->rx_fifo_id)
+ {
+ xport_rpm_ctx[ind].rx_desc =(xport_rpm_ind_type*)&xport_rpm_msg_ram[entry->fifo_offset];
+ xport_rpm_ctx[ind].rx_desc->read_ind = 0;
+ xport_rpm_ctx[ind].rx_fifo = (char*)(xport_rpm_ctx[ind].rx_desc + 1);
+ xport_rpm_ctx[ind].rx_fifo_size = entry->fifo_size;
+ }
+ }
+
+ if (xport_rpm_ctx[ind].tx_desc == NULL || xport_rpm_ctx[ind].rx_desc == NULL)
+ {
+ /* FIFOs not found in MSG RAM ToC. */
+ xport_rpm_ctx[ind].pcfg = NULL;
+ continue;
+ }
+
+ /* Initialize context */
+ xport_rpm_ctx[ind].tx_link_lock = NULL;
+ xport_rpm_ctx[ind].rx_link_lock = NULL;
+
+ /* Initialize GLink transport interface */
+ xport_rpm_ctx[ind].xport_if.tx_cmd_version = &xport_rpm_tx_cmd_version;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_version_ack = &xport_rpm_tx_cmd_version_ack;
+ xport_rpm_ctx[ind].xport_if.set_version = &xport_rpm_set_version;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_ch_open = &xport_rpm_tx_cmd_ch_open;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_ch_close = &xport_rpm_tx_cmd_ch_close;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_open_ack = &xport_rpm_tx_cmd_ch_remote_open_ack;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_ch_remote_close_ack = &xport_rpm_tx_cmd_ch_remote_close_ack;
+ xport_rpm_ctx[ind].xport_if.tx = &xport_rpm_tx;
+ xport_rpm_ctx[ind].xport_if.tx_cmd_set_sigs = &xport_rpm_tx_cmd_set_sigs;
+ xport_rpm_ctx[ind].xport_if.ssr = &xport_rpm_ssr;
+ xport_rpm_ctx[ind].xport_if.mask_rx_irq = &xport_rpm_mask_interrupt;
+ xport_rpm_ctx[ind].xport_if.poll = (poll_fn)&xport_rpm_poll;
+ xport_rpm_ctx[ind].xport_if.wait_link_down = &xport_rpm_wait_link_down;
+
+ /* TODO: glink transport priority */
+ xport_rpm_ctx[ind].xport_if.glink_priority = GLINK_XPORT_RPM;
+
+ /* Setup GLink configuration */
+ xport_rpm_cfg.name = XPORT_RPM_NAME;
+ xport_rpm_cfg.remote_ss = xport_rpm_ctx[ind].pcfg->remote_ss;
+ xport_rpm_cfg.version = &xport_rpm_version;
+ xport_rpm_cfg.version_count = 1;
+ xport_rpm_cfg.max_cid = 0xFF;
+ xport_rpm_cfg.max_iid = 0;
+ if (glink_core_register_transport(&xport_rpm_ctx[ind].xport_if, &xport_rpm_cfg) !=
+ GLINK_STATUS_SUCCESS)
+ {
+ /* Registration failed, set index to invalid. */
+ xport_rpm_ctx[ind].pcfg = NULL;
+ continue;
+ }
+
+ if ( !glink_os_register_isr( xport_rpm_ctx[ind].pcfg->irq_in,
+ (os_isr_cb_fn)xport_rpm_isr,
+ &xport_rpm_ctx[ind]) )
+ {
+ /* ISR registration failed, set index to invalid. */
+ xport_rpm_ctx[ind].pcfg = NULL;
+ continue;
+ }
+
+ /* send link up notification */
+ xport_rpm_ctx[ind].xport_if.glink_core_if_ptr->link_up((glink_transport_if_type *)&xport_rpm_ctx[ind].xport_if);
+ }
+
+ return GLINK_STATUS_SUCCESS;
+}
diff --git a/platform/msm_shared/glink/xport_rpm_config.c b/platform/msm_shared/glink/xport_rpm_config.c
new file mode 100644
index 0000000..1fff513
--- /dev/null
+++ b/platform/msm_shared/glink/xport_rpm_config.c
@@ -0,0 +1,92 @@
+/* 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 "xport_rpm_config.h"
+#include "smem_type.h"
+#include "glink_os_utils.h"
+#include <platform/iomap.h>
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+
+#define XPORT_RPM_MSG_RAM_BASE RPM_SS_MSG_RAM_START_ADDRESS_BASE_PHYS
+#define XPORT_RPM_MSG_RAM_SIZE RPM_SS_MSG_RAM_START_ADDRESS_BASE_SIZE
+
+/** Size of Glink RPM transport ToC in MSG RAM */
+#define XPORT_RPM_MSG_TOC_SIZE 0x100
+
+/*===========================================================================
+ DATA DECLARATIONS
+===========================================================================*/
+const xport_rpm_config_type xport_rpm_config[] =
+{
+ /* LK->Rpm */
+ {
+ "rpm", /* Remote host name */
+ XPORT_RPM_AP2R_ID, /* Tx FIFO ID in RPM ToC */
+ XPORT_RPM_R2AP_ID, /* Rx FIFO ID in RPM ToC */
+ { /* Outgoing interrupt */
+ 8, //DALIPCINT_PROC_RPM,
+ 0, //DALIPCINT_GP_0
+ },
+ 200 /* Incoming interrupt */
+ }
+};
+
+const uint32 xport_rpm_config_num = ARRAY_LENGTH(xport_rpm_config);
+const char* xport_rpm_msg_ram = (char*)XPORT_RPM_MSG_RAM_BASE;
+const uint32* xport_rpm_msg_ram_toc = (uint32*)(XPORT_RPM_MSG_RAM_BASE + XPORT_RPM_MSG_RAM_SIZE - XPORT_RPM_MSG_TOC_SIZE);
+
+/*===========================================================================
+FUNCTION xport_rpm_get_config
+===========================================================================*/
+/**
+
+ Provides a pointer to transport config strucutre.
+
+ @param[in] ind Index of the config
+
+ @return Pointer to transport config strucutre.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+const xport_rpm_config_type* xport_rpm_get_config(uint32 ind)
+{
+ if (ind >= xport_rpm_config_num)
+ {
+ return NULL;
+ }
+
+ return &xport_rpm_config[ind];
+}
diff --git a/platform/msm_shared/include/glink.h b/platform/msm_shared/include/glink.h
new file mode 100644
index 0000000..fe5b823
--- /dev/null
+++ b/platform/msm_shared/include/glink.h
@@ -0,0 +1,580 @@
+/* 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.
+*/
+
+#ifndef GLINK_H
+#define GLINK_H
+
+/**
+ * @file glink.h
+ *
+ * Public API for the GLink
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+#include <stdlib.h>
+
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+/** GLink status/return codes */
+typedef enum {
+ GLINK_STATUS_SUCCESS = 0,
+ GLINK_STATUS_FAILURE,
+ GLINK_STATUS_INVALID_PARAM,
+ GLINK_STATUS_NOT_INIT,
+ GLINK_STATUS_OUT_OF_RESOURCES,
+ GLINK_STATUS_NO_TRANSPORT
+}glink_err_type;
+
+/** List of possible suvsystems */
+/**
+ "apss" Application Processor Subsystem
+ "mpss" Modem subsystem
+ "lpass" Low Power Audio Subsystem
+ "dsps" Sensors Processor
+ "wcnss" Wireless Connectivity Subsystem
+ "rpm" Resource Power Manager processor
+*/
+
+/** Max allowed channel name length */
+#define GLINK_CH_NAME_LEN 32
+
+/* Bit position of DTR/CTS/CD/RI bits in control sigs 32 bit signal map */
+#define SMD_DTR_SIG_SHFT 31
+#define SMD_CTS_SIG_SHFT 30
+#define SMD_CD_SIG_SHFT 29
+#define SMD_RI_SIG_SHFT 28
+
+/** Version number for the glink_link_id_type structure */
+#define GLINK_LINK_ID_VER 0x00000001
+
+/** Macro to initialize the link identifier structure with default values.
+ * It memsets the header to 0 and initializes the header field */
+#define GLINK_LINK_ID_STRUCT_INIT(link_id) \
+ (link_id).xport = 0; \
+ (link_id).remote_ss = 0; \
+ (link_id).link_notifier = 0; \
+ (link_id).handle = 0; \
+ (link_id).version = GLINK_LINK_ID_VER;
+
+/* GLink tx options */
+/* Whether to block and request for remote rx intent in
+ * case it is not available for this pkt tx */
+#define GLINK_TX_REQ_INTENT 0x00000001
+
+/* If the tx call is being made from single threaded context. GLink tries to
+ * flush data into the transport in glink_tx() context, or returns error if
+ * it is not able to do so */
+#define GLINK_TX_SINGLE_THREADED 0x00000002
+
+/* ======================= glink open cfg options ==================*/
+
+/* Specified transport is just the initial transport and migration is possible
+ * to higher-priority transports. Without this flag, the open will fail if
+ * the transport does not exist. */
+#define GLINK_OPT_INITIAL_XPORT 0x00000001
+
+/*===========================================================================
+ TYPE DECLARATIONS
+===========================================================================*/
+/** Enums to identify link state */
+typedef enum {
+ GLINK_LINK_STATE_UP, /* Called after specified link is online */
+ GLINK_LINK_STATE_DOWN /* Called after SSR (before REMOTE_DISCONNECT) */
+} glink_link_state_type;
+
+/** Data structure holding the link state information */
+typedef struct glink_link_info_t {
+ const char* xport; /* Transport name */
+ const char* remote_ss; /* Remote subsystem name */
+ glink_link_state_type link_state; /* Link state */
+}glink_link_info_type;
+
+/* Callback function invoked when link goes up/down */
+typedef void (*glink_link_state_notif_cb)
+(
+ glink_link_info_type *link_info, /* Ptr to link information strcuture */
+ void* priv /* Client private data */
+);
+
+/**
+ * Opaque handle returned by glink_register_link_state_cb. Client uses this
+ * handle to call glink_deregister_link_state_cb() to deregister their
+ * callback
+ *
+ * Client must not modify or try to interpret this value
+ */
+typedef struct glink_link_notif_data_type * glink_link_handle_type;
+
+/** Data structure to provide link information for the link to monitor */
+typedef struct glink_link_id_t {
+ unsigned int version; /* This fields identifies the verion of
+ the structure. Initialized by
+ GLINK_LINK_ID_STRUCT_INIT macro */
+
+ const char* xport; /* NULL = any transport */
+ const char* remote_ss; /* NULL = any subsystem */
+ glink_link_state_notif_cb link_notifier; /* Notification callback */
+ glink_link_handle_type handle; /* Set by glink_register_link_state_cb */
+}glink_link_id_type;
+
+/**
+ * Opaque handle returned by glink_open. Client uses this handle to call into
+ * GLink API for any further activity related to the channel,
+ *
+ * Client must to modify or try to interpret this value
+ */
+typedef struct glink_channel_ctx* glink_handle_type;
+
+/** GLink logical link state notifications */
+typedef enum {
+ /** Channel is fully opened. Both local and remote end have
+ opened channel from their respective ends, and data communication
+ can now take place */
+ GLINK_CONNECTED = 0,
+
+ /** Local side has called glink_close() and remote side has acknowledged
+ this end's close. Client may call glink_open() after this point */
+ GLINK_LOCAL_DISCONNECTED,
+
+ /** Remote side has called glink_close() to close the channel */
+ GLINK_REMOTE_DISCONNECTED
+}glink_channel_event_type;
+
+/** Vector buffer provider type*/
+typedef void* (*glink_buffer_provider_fn)
+(
+ void* iovec, /* vector buffer */
+ size_t offset, /* offset from the beginning of the vector */
+ size_t *size /* size of the returned contiguous buffer */
+);
+
+/** Data receive notification callback type*/
+typedef void (*glink_rx_notification_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ const void *pkt_priv, /* private client data assiciated with the
+ rx intent that client queued earlier */
+ const void *ptr, /* pointer to the received buffer */
+ size_t size, /* size of the packet */
+ size_t intent_used /* size of the intent used for this packet */
+);
+
+/** Vector receive notification callback type*/
+typedef void (*glink_rxv_notification_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ const void *pkt_priv, /* private client data assiciated with the
+ rx intent that client queued earlier */
+ void *iovec, /* pointer to the received vector */
+ size_t size, /* size of the packet */
+ size_t intent_used, /* size of the intent used for this packet */
+ glink_buffer_provider_fn vprovider, /* Buffer provider for virtual space */
+ glink_buffer_provider_fn pprovider /* Buffer provider for physical space */
+);
+
+/** Data transmit notification callback type*/
+typedef void (*glink_tx_notification_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ const void *pkt_priv, /* private client data assiciated with the
+ tx pkt that client queued earlier */
+ const void *ptr, /* pointer to the transmitted buffer */
+ size_t size /* size of the packet */
+);
+
+/** GLink channel state change notification callback type*/
+typedef void (*glink_state_notification_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ glink_channel_event_type event /* Notification event */
+);
+
+/** Request for a receive intent of size req_size is queued. The request
+ * originates from the remote side GLink client. Return true if intent will
+ * be queued or false if intent request will be denied. */
+typedef bool (*glink_notify_rx_intent_req_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ size_t req_size /* Requested size */
+);
+
+/** New intent arrival notification callback type*/
+typedef void (*glink_notify_rx_intent_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ size_t size /* Intent size */
+);
+
+/** Control signal change notification - Invoked when remote side
+ * alters its control signals */
+typedef void (*glink_notify_rx_sigs_cb)
+(
+ glink_handle_type handle, /* handle for the glink channel */
+ const void *priv, /* priv client data passed in glink_open */
+ uint32_t prev, /* Previous remote state */
+ uint32_t curr /* Current remote state */
+);
+
+/** rx_intent abort notification. This callback would be invoked for
+ * every rx_intent that is queued with GLink core at the time the
+ * remote side or local side decides to close the port */
+typedef void(*glink_notify_rx_abort_cb)
+(
+glink_handle_type handle, /* handle for the glink channel */
+const void *priv, /* priv client data passed in glink_open */
+const void *pkt_priv /* pkt specific private data */
+);
+
+/** tx abort notification. This callback would be invoked if client
+ * had queued a tx buffer with glink and it had not been transmitted i.e.
+ * tx_done callback has not been called for this buffer and remote side
+ * or local side closed the port*/
+typedef void(*glink_notify_tx_abort_cb)
+(
+glink_handle_type handle, /* handle for the glink channel */
+const void *priv, /* priv client data passed in glink_open */
+const void *pkt_priv /* pkt specific private data */
+);
+
+/**
+ * Data Structure for GLink logical channel open configuration
+ *
+ * This structure is used by the clients to open a GLink logical channel
+ * when calling glink_open()
+ */
+typedef struct {
+ /** string name for the transport to use (Optional)*/
+ const char *transport;
+
+ /** string name for the remote subsystem to which the user wants to
+ connect */
+ const char *remote_ss;
+
+ /** string name for the channel */
+ const char *name;
+
+ /** bitfield for specifying various options */
+ unsigned options;
+
+ /** Private data for client to maintain context. This data is passed back
+ to client in the notification callbacks */
+ const void *priv;
+
+ /** Data receive notification callback. Optional if notify_rxv is provided */
+ glink_rx_notification_cb notify_rx;
+
+ /** Vector receive notification callback. Optional if notify_rx is provided */
+ glink_rxv_notification_cb notify_rxv;
+
+ /** Data transmit notification callback */
+ glink_tx_notification_cb notify_tx_done;
+
+ /** GLink channel state notification callback */
+ glink_state_notification_cb notify_state;
+
+ /** Intent request from the remote side. Optional */
+ glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+ /** New intent arrival from the remote side */
+ glink_notify_rx_intent_cb notify_rx_intent;
+
+ /** Control signal change notification - Invoked when remote side
+ * alters its control signals. Optional */
+ glink_notify_rx_sigs_cb notify_rx_sigs;
+
+ /** rx_intent abort notification. This callback would be invoked for
+ * every rx_intent that is queued with GLink core at the time the
+ * remote side or local side decides to close the port. Optional */
+ glink_notify_rx_abort_cb notify_rx_abort;
+
+ /** tx abort notification. This callback would be invoked if client
+ * had queued a tx buffer with glink and it had not been transmitted i.e.
+ * tx_done callback has not been called for this buffer and remote side
+ * or local side closed the port. Optional */
+ glink_notify_tx_abort_cb notify_tx_abort;
+
+}glink_open_config_type;
+
+/*===========================================================================
+ GLINK PUBLIC API
+===========================================================================*/
+/**
+ * Regsiters a client specified callback to be invoked when the specified
+ * transport (link) is up/down.
+ *
+ * @param[in] link_id Pointer to the configuration structure for the
+ * xport(link) to be monitored. See glink.h
+ * @param[in] priv Callback data returned to client when callback
+ * is invoked.
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Puts the callback in a queue which gets scanned when a
+ * transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_register_link_state_cb
+(
+ glink_link_id_type *link_id,
+ void* priv
+);
+
+/**
+ * Degsiter the link UP/DOWN notification callback associated with the
+ * provided handle.
+ *
+ * @param[in] handle Callback handler returned by
+ * glink_register_link_state_cb
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Removes the callback in a queue which gets scanned when a
+ * transport(link) comes up OR an SSR happnes.
+ */
+glink_err_type glink_deregister_link_state_cb
+(
+ glink_link_handle_type handle
+);
+
+/**
+ * Opens a logical GLink based on the specified config params
+ *
+ * @param[in] cfg_ptr Pointer to the configuration structure for the
+ * GLink. See glink.h
+ * @param[out] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Allocates channel resources and informs remote host about
+ * channel open.
+ */
+glink_err_type glink_open
+(
+ glink_open_config_type *cfg_ptr,
+ glink_handle_type *handle
+);
+
+/**
+ * Closes the GLink logical channel specified by the handle.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Closes local end of the channel and informs remote host
+ */
+glink_err_type glink_close
+(
+ glink_handle_type handle
+);
+
+/**
+ * Transmit the provided buffer over GLink.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] *data Pointer to the data buffer to be transmitted
+ *
+ * @param[in] size Size of buffer
+ *
+ * @param[in] options Flags specifying how transmission for this buffer
+ * would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_tx
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ const void *data,
+ size_t size,
+ uint32_t options
+);
+
+/**
+ * Transmit the provided vector buffer over GLink.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] *iovec Pointer to the vector buffer to be transmitted
+ *
+ * @param[in] size Size of buffer
+ *
+ * @param[in] vprovider Buffer provider for virtual space
+ *
+ * @param[in] pprovider Buffer provider for physical space
+ *
+ * @param[in] options Flags specifying how transmission for this buffer
+ * would be handled. See GLINK_TX_* flag definitions.
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects Causes remote host to wake-up and process rx pkt
+ */
+glink_err_type glink_txv
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ void *iovec,
+ size_t size,
+ glink_buffer_provider_fn vprovider,
+ glink_buffer_provider_fn pprovider,
+ uint32_t options
+);
+
+/**
+ * Queue one or more Rx intent for the logical GPIC Link channel.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *pkt_priv Per packet private data
+ *
+ * @param[in] size Size of buffer
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects GLink XAL allocates rx buffers for receiving packets
+ */
+glink_err_type glink_queue_rx_intent
+(
+ glink_handle_type handle,
+ const void *pkt_priv,
+ size_t size
+);
+
+/**
+ * Client uses this to signal to GLink layer that it is done with the received
+ * data buffer. This API should be called to free up the receive buffer, which,
+ * in zero-copy mode is actually remote-side's transmit buffer.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] *ptr Pointer to the received buffer
+ *
+ * @param[in] reuse Reuse intent
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects GLink XAL frees the Rx buffer
+ */
+glink_err_type glink_rx_done
+(
+ glink_handle_type handle,
+ const void *ptr,
+ bool reuse
+);
+
+/**
+ * Set the 32 bit control signal field. Depending on the transport, it may
+ * take appropriate actions on the set bit-mask, or transmit the entire
+ * 32-bit value to the remote host.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] sig_value 32 bit signal word
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_set
+(
+ glink_handle_type handle,
+ uint32_t sig_value
+);
+
+/**
+ * Get the local 32 bit control signal bit-field.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_local_get
+(
+ glink_handle_type handle,
+ uint32_t *sig_value
+);
+
+/**
+ * Get the remote 32 bit control signal bit-field.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[out] *sig_value Pointer to a 32 bit signal word to get sig value
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_sigs_remote_get
+(
+ glink_handle_type handle,
+ uint32_t *sig_value
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_H
diff --git a/platform/msm_shared/include/glink_channel_migration.h b/platform/msm_shared/include/glink_channel_migration.h
new file mode 100644
index 0000000..3693660
--- /dev/null
+++ b/platform/msm_shared/include/glink_channel_migration.h
@@ -0,0 +1,141 @@
+/* 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.
+*/
+
+#ifndef GLINK_CH_MGR__H
+#define GLINK_CH_MGR__H
+
+/*===========================================================================
+
+ GLink channel migration Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ FEATURE DEFINITIONS
+===========================================================================*/
+
+/**
+ * This function returns glink_transport_if pointer based on
+ * XPORT priority
+ *
+ * @param[in] prio glink xport prio
+ * @param[in] remote_ss remote subsytem name
+ *
+ * @return pointer to glink_transport_if_type struct
+ *
+ * @sideeffects NONE
+ */
+glink_transport_if_type *glinki_get_xport_from_prio
+(
+ glink_xport_priority prio,
+ const char *remote_ss
+);
+
+/**
+ * This function negotiated xport priorities and gives best
+ * available priority
+ *
+ * @param[in] requested_best_prio priority requested by remote subsytem
+ * @param[in] current_best_prio priority requested by channel on local
+ side
+ *
+ * @return Negotiated xport priority
+ *
+ * @sideeffects NONE
+ */
+glink_xport_priority glinki_negotiate_ch_migration
+(
+ glink_xport_priority requested_prio,
+ glink_xport_priority current_prio
+);
+
+/**
+ * This function searches channel with given name on all available
+ * xports and returns channel context and xport on which channel is
+ * present. These return values are used to negotiate xport priorities
+ * and to decide if channel needs to be migrated from given xport
+ * to negotiated xport
+ *
+ * @param[in] if_ptr transport on which channel is opened
+ * @param[in] name name of the channel
+ * @param[in] is_local_channel flag to notify this function if channel to
+ * be searched will have state REMOTE_OPEN
+ * or LOCAL_OPEN
+ * @param[out] present_ch_ctx channel context to be returned
+ * @param[out] present_if_ptr xport pointer on which channel is open
+ *
+ * @return TRUE - if channel found
+ * FALSE - if channel is not found
+ *
+ * @sideeffects NONE
+ */
+boolean glinki_local_channel_exists
+(
+ glink_transport_if_type *if_ptr,
+ glink_transport_if_type **present_if_ptr,
+ const char *name,
+ glink_channel_ctx_type **present_ch_ctx,
+ boolean is_local_channel
+);
+
+/**
+ * This function sets flag for channel context to represent
+ * that channel is tagged for deletion. This is to cover corner
+ * case where local side might close the channel but channel
+ * context still sticks around and might be found again for
+ * xport negotiation.
+ *
+ * @param[in] if_ptr transport on which channel is opened
+ * @param[in] name name of the channel
+ * @param[in] prio priority of negotiated xport. all channels on
+ * xports other than xport with this prio will be
+ * tagged for deletion
+ *
+ * @return NONE
+ *
+ * @sideeffects NONE
+ */
+void glinki_tag_ch_for_deletion
+(
+ glink_transport_if_type *if_ptr,
+ const char *name,
+ glink_xport_priority prio
+);
+
+#endif /* GLINK_CHANNEL_MIGRATION_H */
diff --git a/platform/msm_shared/include/glink_core_if.h b/platform/msm_shared/include/glink_core_if.h
new file mode 100644
index 0000000..040bf31
--- /dev/null
+++ b/platform/msm_shared/include/glink_core_if.h
@@ -0,0 +1,512 @@
+/* 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.
+*/
+
+#ifndef GLINK_CORE_IF_H
+#define GLINK_CORE_IF_H
+
+/**
+ * @file glink_core_if.h
+ *
+ * Public API for the transport abstraction layer to call into GLINK Core
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_transport_if.h"
+#include "glink_os_utils.h"
+
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+ TYPE DECLARATIONS
+===========================================================================*/
+typedef struct glink_core_version glink_core_version_type;
+
+struct glink_channel_ctx;
+typedef struct glink_channel_ctx glink_channel_ctx_type;
+
+/**
+ * Transport status
+ */
+typedef enum {
+ GLINK_XPORT_REGISTERED = 0,
+ GLINK_XPORT_NEGOTIATING,
+ GLINK_XPORT_LINK_UP,
+
+}glink_transport_status_type;
+
+struct glink_rx_intent {
+ /* Link needed for use with list APIs. Must be at the head of the struct */
+ smem_list_link_type link;
+
+ void *data; /* Pointer to the data buffer to be transmitted */
+ const void *pkt_priv; /* Per packet private data */
+ size_t size; /* Size of data buffer */
+ size_t used; /* Actual valid data in *data field */
+ size_t pkt_sz; /* Size of the packet */
+ uint32 iid; /* Intent ID */
+ void *iovec; /* Pointer to the data buffer to be transmitted */
+ glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+ glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+};
+/** GLink channel states*/
+typedef enum {
+ /** GLink channel state during initialization. No resources have been
+ * allocated for this channel as neither GLink end has actually opened
+ * the channel */
+ GLINK_CH_STATE_CLOSED,
+
+ /** GLink channel state when the local side has opened the channel. GLink
+ * core is waiting for the other end of the channel to open */
+ GLINK_CH_STATE_LOCAL_OPEN,
+
+ /** GLink channel state when it is fully open. This implies that both ends
+ * of the GLink channel are now open. Data transfer can now take place */
+ GLINK_CH_STATE_OPEN,
+
+ /** GLink channel state when remote side has initiated a OPEN operation. */
+ GLINK_CH_STATE_REMOTE_OPEN,
+
+ /** GLink channel state when remote side has initiated a CLOSE operation.
+ * Data cannot be transmitted/received any further on this channel */
+ GLINK_CH_STATE_LOCAL_OPEN_REMOTE_CLOSE,
+
+ /** GLink channel state when the local side has initiated a CLOSE. This
+ * would be followed by a GLINK_STATE_CLOSE state transition after
+ * the remote side has acknowledged the CLOSE request */
+ GLINK_CH_STATE_REMOTE_OPEN_LOCAL_CLOSE,
+
+ /** GLink channel state would transition to SLEEP if the underlying
+ * transport supports low power mode and decides to go into sleep
+ * due to inactivity for some time or any other reason. */
+ GLINK_CH_STATE_SLEEP,
+
+ /** GLink channel state would transition to AWAKE state when underlying
+ * transport layer has powered up the hardware */
+ GLINK_CH_STATE_AWAKE
+}glink_ch_state_type;
+
+/** Indicates that transport is now ready to start negotiation using the
+ * v0 configuration. */
+typedef void (*link_up_fn)
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/** Receive transport version for remote-initiated version negotiation */
+typedef void (*rx_cmd_version_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version, /* Version */
+ uint32 features /* Features */
+);
+
+/** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+typedef void (*rx_cmd_version_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version, /* Version */
+ uint32 features /* Features */
+);
+
+/** Sets the core version used by the transport; called after completing
+ * negotiation.*/
+typedef void (*set_core_version_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version /* Version */
+);
+
+/** Receive remote channel open request; expected response is
+ * glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+typedef void (*rx_cmd_ch_remote_open_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ const char *name, /* String name for the logical channel */
+ glink_xport_priority prio /* priority of xport */
+);
+
+/** This function is invoked by the transport in response to
+ * glink_transport_if_type:: tx_cmd_ch_open */
+typedef void (*rx_cmd_ch_open_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ glink_xport_priority prio
+);
+
+/** This function is invoked by the transport in response to
+ * glink_transport_if_type:: tx_cmd_ch_close */
+typedef void (*rx_cmd_ch_close_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid /* Local channel ID */
+);
+
+/** Remote channel close request; will result in sending
+ * glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+typedef void (*rx_cmd_ch_remote_close_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid /* Remote channel ID */
+);
+
+/** Process local state transition */
+typedef void (*ch_state_local_trans_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ glink_ch_state_type new_state /* New local channel state */
+);
+
+/** Transport invokes this call on receiving remote RX intent */
+typedef void (*rx_cmd_remote_rx_intent_put_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 riid, /* Remote intent ID */
+ size_t size /* Size of receive intent */
+);
+
+/** Get receive packet context (if successful, should be followed by call to
+ rx_put_pkt_ctx) */
+typedef glink_rx_intent_type* (*rx_get_pkt_ctx_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 liid /* Local intent ID */
+);
+
+/** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+ packet). */
+typedef void (*rx_put_pkt_ctx_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ glink_rx_intent_type *intent_ptr, /* Fragment ptr */
+ boolean complete /* True if pkt is complete */
+);
+
+/** Transport invokes this call to inform GLink that remote side is
+ * done with previous transmitted packet. */
+typedef void (*rx_cmd_tx_done_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 riid, /* Remote intent ID */
+ boolean reuse /* Reuse intent */
+);
+
+/** Remote side is requesting an RX intent */
+typedef void (*rx_cmd_remote_rx_intent_req_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ size_t size /* Size of the requested intent */
+);
+
+/** ACK to RX Intent Request */
+typedef void (*rx_cmd_rx_intent_req_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ boolean granted /* True if RX Intent will be queued, FALSE
+ if request will not be granted. */
+);
+
+/** If transport was full and could not continue a transmit operation,
+ * then it will call this function to notify the core that it is ready to
+ * resume transmission. */
+typedef void (*tx_resume_fn)
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/** Received 32-bit signals value from remote side. It is passed on to
+ * the client */
+typedef void (*rx_cmd_remote_sigs_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 remote_sigs /* Remote control signals */
+);
+
+/** Channel open config verification */
+typedef boolean(*verify_open_cfg_fn)
+(
+ glink_channel_ctx_type *ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel initialization */
+typedef glink_err_type (*channel_init_fn)
+(
+ glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel cleanup */
+typedef void (*channel_cleanup_fn)
+(
+ glink_channel_ctx_type *open_ch_ctx /* Pointer to the channel context */
+);
+
+/** Channel receive pkt */
+typedef void(*channel_receive_pkt_fn)
+(
+ glink_channel_ctx_type *open_ch_ctx, /* Pointer to the channel context */
+ glink_rx_intent_type *intent_ptr /* Pointer to the intent context */
+);
+
+/** Use remote intent */
+typedef glink_err_type(*use_rm_intent_fn)
+(
+ glink_channel_ctx_type *open_ch_ctx, /* Pointer to the channel context */
+ glink_core_tx_pkt_type *pctx, /* Pointer to the packet context */
+ boolean req_intent /* Request intent flag */
+);
+
+
+/** Transport specific data pointer that transport may choose fill in
+ * with some data */
+struct glink_core_xport_ctx
+{
+ /* Transport name */
+ char xport[32];
+
+ /* Remote subsystem name */
+ char remote_ss[32];
+
+ /** Keep track of version array index in use */
+ const glink_core_version_type *version_array;
+
+ /** Keep track of version array index in use */
+ uint32 version_indx;
+
+ /* Keeps track of the current status of the transport */
+ glink_transport_status_type status;
+
+ /* Transport's capabilities */
+ uint32 xport_capabilities;
+
+ /* Free lcid */
+ uint32 free_lcid;
+
+ /* Keeps track of the open channels for this transport/edge combination */
+ smem_list_type open_list;
+
+ /* Critical section to protect access to open_list */
+ os_cs_type channel_q_cs;
+
+ /* Local channel intents queued so far. This also helps determining liid
+ * when client queues new rx intents locally */
+ uint32 liid;
+
+ /* Critical section to protect access to liid allocation */
+ os_cs_type liid_cs;
+
+ /* channel open config verification */
+ verify_open_cfg_fn verify_open_cfg;
+
+ /* channel init function */
+ channel_init_fn channel_init;
+
+ /* channel cleanup function */
+ channel_cleanup_fn channel_cleanup;
+
+ /* channel receive pkt */
+ channel_receive_pkt_fn channel_receive_pkt;
+
+ /** Use remote intent */
+ use_rm_intent_fn use_rm_intent;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * for logical channel control state update and data Tx/Rx notifications.
+ */
+struct glink_core_if
+{
+ /** Indicates that transport is now ready to start negotiation using the
+ * v0 configuration. */
+ link_up_fn link_up;
+
+
+ /** Receive transport version for remote-initiated version negotiation */
+ rx_cmd_version_fn rx_cmd_version;
+
+
+ /** Receive ACK to previous glink_transport_if_type::tx_cmd_version command */
+ rx_cmd_version_ack_fn rx_cmd_version_ack;
+
+ /** Sets the core version used by the transport; called after completing
+ * negotiation.*/
+ set_core_version_fn set_core_version;
+
+ /** Receive remote channel open request; expected response is
+ * glink_transport_if_type:: tx_cmd_ch_remote_open_ack */
+ rx_cmd_ch_remote_open_fn rx_cmd_ch_remote_open;
+
+
+ /** This function is invoked by the transport in response to
+ * glink_transport_if_type:: tx_cmd_ch_open */
+ rx_cmd_ch_open_ack_fn rx_cmd_ch_open_ack;
+
+
+ /** This function is invoked by the transport in response to
+ * glink_transport_if_type:: tx_cmd_ch_close */
+ rx_cmd_ch_close_ack_fn rx_cmd_ch_close_ack;
+
+
+ /** Remote channel close request; will result in sending
+ * glink_transport_if_type:: tx_cmd_ch_remote_close_ack */
+ rx_cmd_ch_remote_close_fn rx_cmd_ch_remote_close;
+
+
+ /** Process local state transition */
+ ch_state_local_trans_fn ch_state_local_trans;
+
+
+ /** Transport invokes this call on receiving remote RX intent */
+ rx_cmd_remote_rx_intent_put_fn rx_cmd_remote_rx_intent_put;
+
+ /** Get receive packet context (if successful, should be followed by call to
+ rx_put_pkt_ctx) */
+ rx_get_pkt_ctx_fn rx_get_pkt_ctx;
+
+ /** Receive a packet fragment (must have previously received an rx_cmd_rx_data
+ packet). */
+ rx_put_pkt_ctx_fn rx_put_pkt_ctx;
+
+ /** Transport invokes this call to inform GLink that remote side is
+ * done with previous transmitted packet. */
+ rx_cmd_tx_done_fn rx_cmd_tx_done;
+
+ /** Remote side is requesting an RX intent */
+ rx_cmd_remote_rx_intent_req_fn rx_cmd_remote_rx_intent_req;
+
+ /** ACK to RX Intent Request */
+ rx_cmd_rx_intent_req_ack_fn rx_cmd_rx_intent_req_ack;
+
+ /** Received 32-bit signals value from remote side. It is passed on to
+ * the client */
+ rx_cmd_remote_sigs_fn rx_cmd_remote_sigs;
+
+ /** If transport was full and could not continue a transmit operation,
+ * then it will call this function to notify the core that it is ready to
+ * resume transmission. */
+ tx_resume_fn tx_resume;
+};
+
+/** Feature negotiation function. The version negotiation starts out using
+ * the full feature set from the features element and then calls this
+ * function with a subset passed into the features argument. This
+ * function should filter passed in features with the supported feature
+ * set. For simple cases, a bitwise AND can be used, but for more
+ * complicated cases (such as when features are mutually exclusive),
+ * this function enables a more complex negotiation sequence.
+ */
+typedef uint32 (*negotiate_features_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface
+ instance */
+ const glink_core_version_type *version_ptr, /* Version structure */
+ uint32 features /* Subset of features based on
+ negotiation */
+);
+
+/**
+ * Version structure
+ */
+struct glink_core_version {
+ uint32 version; /* Version number */
+ uint32 features; /* Set of features supported in
+ this version */
+
+ /** Feature negotiation function. The version negotiation starts out using
+ * the full feature set from the features element and then calls this
+ * function with a subset passed into the features argument. This
+ * function should filter passed in features with the supported feature
+ * set. For simple cases, a bitwise AND can be used, but for more
+ * complicated cases (such as when features are mutually exclusive),
+ * this function enables a more complex negotiation sequence.
+ */
+ negotiate_features_fn negotiate_features;
+};
+
+/**
+ * Data Structure for Transport abstraction layer to call into GLink Core
+ * while registering with GLink
+ */
+typedef struct {
+ const char *name; /* Name of the transport */
+ const char *remote_ss; /* Remote host name */
+ const glink_core_version_type *version; /* Array of supported versions */
+ size_t version_count; /* Number of elements in version[] */
+ uint32 max_cid; /* Max channel ID supported by
+ transport */
+ uint32 max_iid; /* Max Rx intent ID supported by
+ transport */
+}glink_core_transport_cfg_type;
+
+/*===========================================================================
+ PUBLIC FUNCTION DECLARATIONS
+===========================================================================*/
+/*===========================================================================
+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
+);
+
+#endif //GLINK_CORE_IF_H
+
diff --git a/platform/msm_shared/include/glink_internal.h b/platform/msm_shared/include/glink_internal.h
new file mode 100644
index 0000000..96b0a59
--- /dev/null
+++ b/platform/msm_shared/include/glink_internal.h
@@ -0,0 +1,845 @@
+/* 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.
+*/
+
+#ifndef GLINK_INTERNAL_H
+#define GLINK_INTERNAL_H
+
+/*===========================================================================
+
+ GLink Core Internal Header File
+
+===========================================================================*/
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "glink_core_if.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ FEATURE DEFINITIONS
+===========================================================================*/
+#define GLINK_VERSION 0
+#define GLINK_FEATURE_FLAGS 0
+#define GLINK_NUM_HOSTS 7
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+#define GLINK_LOG_EVENT(type, ch_name, xport, remote_ss, param) \
+ glink_mem_log(__FUNCTION__, __LINE__, type, ch_name, xport, remote_ss, param);
+
+#define GLINK_MEM_LOG_SIZE 128
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+typedef enum {
+ GLINK_EVENT_INIT,
+ GLINK_EVENT_REGISTER_XPORT,
+ GLINK_EVENT_CH_OPEN,
+ GLINK_EVENT_CH_CLOSE,
+ GLINK_EVENT_CH_TX,
+ GLINK_EVENT_CH_Q_RX_INTENT,
+ GLINK_EVENT_CH_RX_DONE,
+ GLINK_EVENT_LINK_UP,
+ GLINK_EVENT_RX_CMD_VER,
+ GLINK_EVENT_RM_CH_OPEN,
+ GLINK_EVENT_CH_OPEN_ACK,
+ GLINK_EVENT_CH_CLOSE_ACK,
+ GLINK_EVENT_CH_REMOTE_CLOSE,
+ GLINK_EVENT_CH_STATE_TRANS,
+ GLINK_EVENT_CH_INTENT_PUT,
+ GLINK_EVENT_CH_RX_DATA,
+ GLINK_EVENT_CH_RX_DATA_FRAG,
+ GLINK_EVENT_CH_GET_PKT_CTX,
+ GLINK_EVENT_CH_PUT_PKT_CTX,
+ GLINK_EVENT_CH_TX_DONE,
+ GLINK_EVENT_CH_SIG_SET,
+ GLINK_EVENT_CH_SIG_L_GET,
+ GLINK_EVENT_CH_SIG_R_GET,
+ GLINK_EVENT_XPORT_INTERNAL,
+}glink_log_event_type;
+
+typedef struct _glink_channel_intents_type {
+ /* Critical section to protest access to intent queues */
+ os_cs_type intent_q_cs;
+
+ /* Event that glink_tx waits on and blocks until remote rx_intents
+ * are available */
+ os_event_type rm_intent_avail_evt;
+
+ /* Size of requested intent that this channel wait on */
+ size_t rm_intent_req_size;
+
+ /* Linked list of remote Rx intents. Data can be transmitted only when
+ * remote intents are available */
+ smem_list_type remote_intent_q;
+
+ /* Linked list of remote Rx intents which local GLink core has used to
+ * transmit data, and are pending Tx complete */
+ smem_list_type remote_intent_pending_tx_q;
+
+ /* Linked list of local Rx intents. Data can be received only when
+ * local intents are available */
+ smem_list_type local_intent_q;
+
+ /* Linked list of remote Rx intents held by the clients */
+ smem_list_type local_intent_client_q;
+
+ /* Read intent being gathered */
+ glink_rx_intent_type *cur_read_intent;
+
+} glink_channel_intents_type;
+
+struct glink_channel_ctx {
+ /* Link needed for use with list APIs. Must be at the head of the struct */
+ smem_list_link_type link;
+
+ /* Channel name */
+ char name[GLINK_CH_NAME_LEN];
+
+ /* Local channel ID */
+ uint32 lcid;
+
+ /* Remote Channel ID */
+ uint32 rcid;
+
+ /* Channel state */
+ glink_ch_state_type state;
+
+ /* Channel local control signal state */
+ uint32 local_sigs;
+
+ /* Channel remote control signal state */
+ uint32 remote_sigs;
+
+ /* Critical section to protect tx operations */
+ os_cs_type tx_cs;
+
+ /* channel intent collection */
+ glink_channel_intents_type *pintents;
+
+ /* Interface pointer with with this channel is registered */
+ glink_transport_if_type *if_ptr;
+
+ /** Private data for client to maintain context. This data is passed back
+ * to client in the notification callbacks */
+ const void *priv;
+
+ /** Data receive notification callback */
+ glink_rx_notification_cb notify_rx;
+
+ /** Vector receive notification callback */
+ glink_rxv_notification_cb notify_rxv;
+
+ /** Data transmit notification callback */
+ glink_tx_notification_cb notify_tx_done;
+
+ /** GLink channel state notification callback */
+ glink_state_notification_cb notify_state;
+
+ /** Intent request from the remote side */
+ glink_notify_rx_intent_req_cb notify_rx_intent_req;
+
+ /** New intent arrival from the remote side */
+ glink_notify_rx_intent_cb notify_rx_intent;
+
+ /** Control signal change notification - Invoked when remote side
+ * alters its control signals */
+ glink_notify_rx_sigs_cb notify_rx_sigs;
+
+ /** rx_intent abort notification. This callback would be invoked for
+ * every rx_intent that is queued with GLink core at the time the
+ * remote side or local side decides to close the port. Optional */
+ glink_notify_rx_abort_cb notify_rx_abort;
+
+ /** tx abort notification. This callback would be invoked if client
+ * had queued a tx buffer with glink and it had not been transmitted i.e.
+ * tx_done callback has not been called for this buffer and remote side
+ * or local side closed the port. Optional */
+ glink_notify_tx_abort_cb notify_tx_abort;
+
+ /* glink transport if pointer for preferred channel */
+ glink_transport_if_type *req_if_ptr;
+
+ /* reference count for no of times channel open/close has been called */
+ uint32 ref_count;
+
+ /* flag to check if channel is marked for deletion
+ * This is workaround to prevent channel migration algorithm from finding channel
+ * which should be closed but has not been closed yet. This case occurs when glink_close
+ * is called for closing channel on initial xport and it is being opened on other xport.
+ * This may lead to remote side opening channel on neogitated xport from which local side
+ * will get remote open again. In this case channel to be closed will be found for negotiation
+ * on initial xport again and channel migration algorithm will be triggered(again) */
+ boolean tag_ch_for_close;
+
+ /* save glink open config options */
+ uint32 ch_open_options;
+};
+
+
+typedef struct _glink_mem_log_entry_type {
+ const char *func;
+ uint32 line;
+ glink_log_event_type type;
+ const char *msg;
+ const char *xport;
+ const char *remote_ss;
+ uint32 param;
+} glink_mem_log_entry_type;
+
+/* Structure to store link notification callbacks */
+typedef struct {
+ /* Link needed for use with list APIs. Must be at the head of the struct */
+ smem_list_link_type link;
+
+ const char* xport; /* NULL = any transport */
+ const char* remote_ss; /* NULL = any subsystem */
+ glink_link_state_notif_cb link_notifier; /* Notification callback */
+ void *priv; /* Notification priv ptr */
+} glink_link_notif_data_type;
+
+
+/*===========================================================================
+ GLOBAL DATA DECLARATIONS
+===========================================================================*/
+extern os_cs_type *glink_transport_q_cs;
+extern const char *glink_hosts_supported[GLINK_NUM_HOSTS];
+extern smem_list_type glink_registered_transports[];
+
+/*===========================================================================
+ LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION glink_link_up
+
+DESCRIPTION Indicates that transport is now ready to start negotiation
+ using the v0 configuration
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_link_up
+(
+ glink_transport_if_type *if_ptr
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_version
+
+DESCRIPTION Receive transport version for remote-initiated version
+ negotiation
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Remote Version
+
+ features Remote Features
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_version
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_version_ack
+
+DESCRIPTION Receive ACK to previous glink_transport_if::tx_cmd_version
+ command
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Remote Version
+
+ features Remote Features
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_version_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 version,
+ uint32 features
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_remote_open
+
+DESCRIPTION Receive remote channel open request; Calls
+ glink_transport_if:: tx_cmd_ch_remote_open_ack as a result
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ *name String name for logical channel
+
+ prio requested xport priority from remote side
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_open
+(
+ glink_transport_if_type *if_ptr,
+ uint32 rcid,
+ const char *name,
+ glink_xport_priority prio
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_open_ack
+
+DESCRIPTION This function is invoked by the transport in response to
+ glink_transport_if:: tx_cmd_ch_open
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ lcid Local Channel ID
+
+ prio Negotiated xport priority obtained from remote side
+ after negotiation happened on remote side
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_open_ack
+(
+ glink_transport_if_type *if_ptr,
+ uint32 lcid,
+ glink_xport_priority prio
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_close_ack
+
+DESCRIPTION This function is invoked by the transport in response to
+ glink_transport_if_type:: tx_cmd_ch_close
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ lcid Local Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_close_ack
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid /* Local channel ID */
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_ch_remote_close
+
+DESCRIPTION Remote channel close request; will result in sending
+ glink_transport_if_type:: tx_cmd_ch_remote_close_ack
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_ch_remote_close
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid /* Remote channel ID */
+);
+
+/*===========================================================================
+FUNCTION glink_ch_state_local_trans
+
+DESCRIPTION Process local state transition
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_ch_state_local_trans
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ glink_ch_state_type new_state /* New local channel state */
+);
+
+/*===========================================================================
+FUNCTION glink_rx_put_pkt_ctx
+
+DESCRIPTION Transport invokes this call to receive a packet fragment (must
+ have previously received an rx_cmd_rx_data packet)
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ *intent_ptr Pointer to the intent fragment
+
+ complete True if pkt is complete
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_put_pkt_ctx
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ glink_rx_intent_type *intent_ptr, /* Fragment ptr */
+ boolean complete /* True if pkt is complete */
+);
+
+/*===========================================================================
+FUNCTION glink_rx_cmd_remote_sigs
+
+DESCRIPTION Transport invokes this call to inform GLink of remote side
+ changing its control signals
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ rcid Remote Channel ID
+
+ remote_sigs Remote signal state.
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_rx_cmd_remote_sigs
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ uint32 remote_sigs /* Remote control signals */
+);
+
+/*===========================================================================
+FUNCTION glink_tx_resume
+
+DESCRIPTION If transport was full and could not continue a transmit
+ operation, then it will call this function to notify the core
+ that it is ready to resume transmission.
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_tx_resume
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/*===========================================================================
+FUNCTION glink_set_core_version
+
+DESCRIPTION Sets the core version used by the transport; called after
+ completing negotiation.
+
+ARGUMENTS *if_ptr Pointer to interface instance; must be unique
+ for each edge
+
+ version Negotiated transport version
+
+RETURN VALUE None.
+
+SIDE EFFECTS None
+===========================================================================*/
+void glink_set_core_version
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version /* Version */
+);
+
+/*===========================================================================
+ CHANNEL CONTEXT APIS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION glinki_ch_is_fully_opened
+
+DESCRIPTION Determine if both the local and remote channel state is fully
+ open
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+RETURN VALUE True if fully opened, FALSE otherwise.
+
+SIDE EFFECTS None
+===========================================================================*/
+boolean glinki_ch_is_fully_opened
+(
+ glink_channel_ctx_type *ctx
+);
+
+
+/*===========================================================================
+FUNCTION glinki_ch_push_local_rx_intent
+
+DESCRIPTION Create and push a local receive intent to internal list
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ *pkt_priv - Client-provided opaque data
+
+ size - Size of Receive Intent
+
+RETURN VALUE Pointer to the new intent
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_push_local_rx_intent
+(
+ glink_channel_ctx_type *ctx,
+ const void *pkt_priv,
+ size_t size
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_get_local_rx_intent
+
+DESCRIPTION Lookup a local receive intent
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ liid - Local Receive Intent ID
+
+RETURN VALUE Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent
+(
+ glink_channel_ctx_type *ctx,
+ uint32 liid
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_remove_local_rx_intent
+
+DESCRIPTION Removes Local Receive Intent ID
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ liid - Local Receive Intent ID
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glinki_ch_remove_local_rx_intent
+(
+ glink_channel_ctx_type *ctx,
+ uint32 liid
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_set_local_rx_intent_notified
+
+DESCRIPTION Sets the state of the intent as client-notified
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glinki_ch_set_local_rx_intent_notified
+(
+ glink_channel_ctx_type *ctx,
+ glink_rx_intent_type *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_get_local_rx_intent_notified
+
+DESCRIPTION Lookup a Local Receive Intent ID that is in the client-notified
+ state
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ *ptr - Data pointer of receive buffer from client
+ (passed in through glink_rx_done)
+
+RETURN VALUE Pointer to the intent or NULL if not match is found.
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_rx_intent_type* glinki_ch_get_local_rx_intent_notified
+(
+ glink_channel_ctx_type *ctx,
+ void *ptr
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_remove_local_rx_intent_notified
+
+DESCRIPTION Removes the Local Receive Intent
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ *intent_ptr - Pointer to the receive intent
+
+RETURN VALUE New channel context or NULL
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_channel_ctx_type* glinki_ch_remove_local_rx_intent_notified
+(
+ glink_channel_ctx_type *ctx,
+ glink_rx_intent_type *intent_ptr
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_push_remote_rx_intent
+
+DESCRIPTION Adds a new Remote Receive Intent
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ size - Size of the Remote Receive Intent
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glinki_ch_push_remote_rx_intent
+(
+ glink_channel_ctx_type *ctx,
+ size_t size
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_pop_remote_rx_intent
+
+DESCRIPTION Removes a Remote Receive Intent
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ size - Size of the Remote Receive Intent
+
+ *riid_ptr - Pointer to the Remote Receive Intent
+
+RETURN VALUE Standard GLink Err code.
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_err_type glinki_ch_pop_remote_rx_intent
+(
+ glink_channel_ctx_type *ctx,
+ size_t size,
+ uint32 *riid_ptr
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_get_tx_pending_remote_done
+
+DESCRIPTION Lookup packet transmit context for a packet that is waiting for
+ the remote-done notification.
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ riid - Remote Receive Intent ID
+
+RETURN VALUE Pointer to the transmit packet context or NULL if not match is
+ found.
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_core_tx_pkt_type* glinki_ch_get_tx_pending_remote_done
+(
+ glink_channel_ctx_type *ctx,
+ uint32 riid
+);
+
+/*===========================================================================
+FUNCTION glinki_ch_remove_tx_pending_remote_done
+
+DESCRIPTION Removes a packet transmit context for a packet that is waiting
+ for the remote-done notification.
+
+ARGUMENTS *cfg_ptr - Pointer to channel context
+
+ *tx_pkt - Pointer to the packet context to remove
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+void glinki_ch_remove_tx_pending_remote_done
+(
+ glink_channel_ctx_type *ctx,
+ glink_core_tx_pkt_type *tx_pkt
+);
+
+/*===========================================================================
+FUNCTION glinki_add_ch_to_xport
+
+DESCRIPTION Add remote/local channel context to xport open channel queue
+
+ARGUMENTS *if_ptr - Pointer to xport if on which channel is to
+ be opened
+ *req_if_ptr - Pointer to xport if on which channel
+ actually wants to open
+ *ch_ctx - channel context
+ **allocated_ch_ctx - Pointer to channel context pointer
+ local_open - flag to determine if channel is opened
+ locally or remotely
+ migration state - flag to identify whether channel migration
+ negotiation is done
+ TRUE - negotiation is not complete
+ FALSE - negotiation is complete.
+ channel is being opened on same xport as negotiated
+ prio - negotiated xport priority
+ (used to send priority via remote_open_ack to
+ remote side)
+ *tx_pkt - Pointer to the packet context to remove
+
+RETURN VALUE None
+
+SIDE EFFECTS None
+===========================================================================*/
+glink_err_type glinki_add_ch_to_xport
+(
+ glink_transport_if_type *if_ptr,
+ glink_transport_if_type *req_if_ptr,
+ glink_channel_ctx_type *ch_ctx,
+ glink_channel_ctx_type **allocated_ch_ctx,
+ unsigned int local_open,
+ boolean migration_state,
+ glink_xport_priority prio
+);
+
+void glink_mem_log
+(
+ const char *func,
+ uint32 line,
+ glink_log_event_type type,
+ const char *msg,
+ const char *xport,
+ const char *remote_ss,
+ uint32 param
+);
+
+/*===========================================================================
+FUNCTION glink_core_setup
+===========================================================================*/
+/**
+
+ Initializes internal core functions based on the transport capabilities.
+
+ @param[in] if_ptr The Pointer to the interface instance.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void glink_core_setup(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION glink_core_setup_full_xport
+===========================================================================*/
+/**
+
+ Initializes internal core functions for the full-featured transport.
+
+ @param[in] if_ptr The Pointer to the interface instance.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void glink_core_setup_full_xport(glink_transport_if_type *if_ptr);
+
+/*===========================================================================
+FUNCTION glink_core_setup_intentless_xport
+===========================================================================*/
+/**
+
+ Initializes internal core functions for the intentless transport.
+
+ @param[in] if_ptr The Pointer to the interface instance.
+
+ @return None.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void glink_core_setup_intentless_xport(glink_transport_if_type *if_ptr);
+
+#endif /* GLINK_INTERNAL_H */
diff --git a/platform/msm_shared/include/glink_os_type.h b/platform/msm_shared/include/glink_os_type.h
new file mode 100644
index 0000000..091ad05
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_type.h
@@ -0,0 +1,97 @@
+/* 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.
+*/
+
+#ifndef OS_TYPE_H
+#define OS_TYPE_H
+
+/*===========================================================================
+
+ G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+#include <string.h>
+#include <assert.h>
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+
+#define OS_LOG_INIT( ) glink_os_log_init()
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+#define DALSYS_SYNC_OBJ_SIZE_BYTES 40
+#define DALSYS_EVENT_OBJ_SIZE_BYTES 80
+
+typedef bool boolean;
+typedef uint64_t uint64;
+typedef uint32_t uint32;
+typedef long int32;
+#define TRUE 1
+#define FALSE 0
+
+typedef struct DALSYSEventObj DALSYSEventObj;
+
+struct DALSYSEventObj
+{
+ unsigned long long _bSpace[DALSYS_EVENT_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+
+typedef struct DALSYSSyncObj DALSYSSyncObj;
+struct DALSYSSyncObj
+{
+ unsigned long long _bSpace[DALSYS_SYNC_OBJ_SIZE_BYTES/sizeof(unsigned long long)];
+};
+
+typedef DALSYSSyncObj os_cs_type;
+
+typedef void ( *os_timer_cb_fn )( void *cb_data );
+
+typedef struct
+{
+ void * dal_event;
+ DALSYSEventObj dal_obj_memory;
+}os_event_type;
+
+typedef void ( *os_isr_cb_fn )( void *cb_data );
+
+typedef struct os_ipc_intr_struct
+{
+ uint32_t processor;
+ uint32_t irq_out;
+} os_ipc_intr_type;
+
+#endif /* OS_TYPE_H */
diff --git a/platform/msm_shared/include/glink_os_utils.h b/platform/msm_shared/include/glink_os_utils.h
new file mode 100644
index 0000000..e0a1613
--- /dev/null
+++ b/platform/msm_shared/include/glink_os_utils.h
@@ -0,0 +1,258 @@
+/* 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.
+*/
+
+#ifndef OS_UTILS_H
+#define OS_UTILS_H
+
+/*===========================================================================
+
+ G-Link OS Specific types/functions
+
+===========================================================================*/
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+#include <glink_os_type.h>
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION glink_os_cs_init
+===========================================================================*/
+/**
+ Initializes a Critical Section
+
+ @param[in] cs pointer to critical section object allocated by caller.
+
+ @return
+ TRUE if critical section was initialized, FALSE otherwise
+*/
+/*=========================================================================*/
+bool glink_os_cs_init( os_cs_type *cs );
+
+/*===========================================================================
+ FUNCTION glink_os_cs_acquire
+===========================================================================*/
+/**
+ Lock a critical section
+
+ @param[in] cs Pointer the the critical section
+
+ @return None.
+*/
+/*=========================================================================*/
+void glink_os_cs_acquire( os_cs_type *cs );
+
+/*===========================================================================
+ FUNCTION glink_os_cs_release
+===========================================================================*/
+/**
+ Unlock a critical section
+
+ @param[in] cs Pointer the the critical section
+
+ @return None.
+*/
+/*=========================================================================*/
+void glink_os_cs_release( os_cs_type *cs );
+
+/*===========================================================================
+ FUNCTION glink_os_cs_create
+===========================================================================*/
+/**
+ Create and initializesa Critical Section
+
+ @return The critical section.
+*/
+/*=========================================================================*/
+os_cs_type *glink_os_cs_create( void );
+
+/*===========================================================================
+ FUNCTION glink_os_malloc
+===========================================================================*/
+/**
+ Dynamically allocate a region of memory from the heap. The region should be
+ freed using \c glink_os_free when no longer used.
+
+ @param[in] size The number of bytes to be allocated.
+
+ @return The pointer to the region of memory that was allocated.
+ NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_malloc( size_t size );
+
+/*===========================================================================
+ FUNCTION glink_os_calloc
+===========================================================================*/
+/**
+ Dynamically allocate a region of memory from the heap and initialize with
+ the zeroes. The region should be freed using \c glink_os_free
+ when no longer used.
+
+ @param[in] size The number of bytes to be allocated.
+
+ @return The pointer to the region of memory that was allocated.
+ NULL if the allocation failed.
+*/
+/*=========================================================================*/
+void *glink_os_calloc( size_t size );
+
+/*===========================================================================
+ FUNCTION glink_os_free
+===========================================================================*/
+/**
+ Free a region of memory that was allocated by \c glink_os_malloc.
+
+ @param[in] pMem The reference to the region of memory to be freed.
+
+ @return NA
+*/
+/*=========================================================================*/
+void glink_os_free( void *pMem );
+
+/*===========================================================================
+ FUNCTION glink_os_string_copy
+===========================================================================*/
+/**
+ Copies the source string into the destination buffer until
+ size is reached, or until a '\0' is encountered. If valid,
+ the destination string will always be NULL deliminated.
+
+ @param[in] dst The destination string, contents will be updated.
+ @param[in] src The source string
+ @param[in] size The maximum copy size (size of dst)
+
+ @return
+ The destination string pointer, dst.
+*/
+/*==========================================================================*/
+char *glink_os_string_copy(char *dst, const char *src, uint32_t size);
+
+/*===========================================================================
+ FUNCTION glink_os_string_compare
+===========================================================================*/
+/**
+ Compares two strings delimited by size or NULL character.
+
+ @param[in] s1 String 1
+ @param[in] s2 String 2
+ @param[in] size The maximum number of characters to compare
+
+ @return
+ 0 if strings are identical (up to size characters), non-zero otherwise
+*/
+/*==========================================================================*/
+long glink_os_string_compare( const char *s1, const char *s2, uint32_t size );
+
+/*===========================================================================
+ FUNCTION glink_os_copy_mem
+===========================================================================*/
+/**
+ Copies the source buffer into the destination buffer.
+
+ @param[in] dst The destination, contents will be updated.
+ @param[in] src The source
+ @param[in] size The maximum copy size (size of dst)
+
+ @return
+ The destination string pointer, dst.
+*/
+/*==========================================================================*/
+void glink_os_copy_mem(void *dst, const void *src, uint32_t size);
+
+/*===========================================================================
+ FUNCTION glink_os_register_isr
+===========================================================================*/
+/**
+ Registers ISR with the interrupt controller
+
+ @param[in] irq_in Interrupt to register for
+ @param[in] isr Callback to be invoked when interrupt fires
+ @param[in] cb_data Data to be provided to the callback
+
+ @return true if registration was successful, false otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_register_isr( uint32_t irq_in, os_isr_cb_fn isr, void *cb_data );
+
+/*===========================================================================
+ FUNCTION glink_os_deregister_isr
+===========================================================================*/
+/**
+ De-registers ISR with the interrupt controller
+
+ @param[in] irq_in Interrupt to deregister for
+
+ @return TRUE if de-registration was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_deregister_isr( uint32_t irq_in );
+
+/*===========================================================================
+ FUNCTION glink_os_enable_interrupt
+===========================================================================*/
+/**
+ Enables the interrupt in the interrupt controller
+
+ @param[in] irq_in Interrupt to enable
+
+ @return TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_enable_interrupt( uint32_t irq_in );
+
+/*===========================================================================
+ FUNCTION glink_os_disable_interrupt
+===========================================================================*/
+/**
+ Disables the interrupt in the interrupt controller
+
+ @param[in] irq_in Interrupt to disable
+
+ @return TRUE if operation was successful, FALSE otherwise.
+*/
+/*=========================================================================*/
+bool glink_os_disable_interrupt( uint32_t irq_in );
+
+bool glink_os_log_init( void );
+
+#endif /* OS_UTILS_H */
diff --git a/platform/msm_shared/include/glink_rpm.h b/platform/msm_shared/include/glink_rpm.h
new file mode 100644
index 0000000..c7cfdeb
--- /dev/null
+++ b/platform/msm_shared/include/glink_rpm.h
@@ -0,0 +1,108 @@
+/* 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.
+*/
+
+#ifndef GLINK_RPM_H
+#define GLINK_RPM_H
+
+/**
+ * @file glink_rpm.h
+ *
+ * Public API for the GLink-RPM
+ */
+
+/** \defgroup glink GLink
+ * \ingroup SMD
+ *
+ * GLink reliable, in-order, datagram-based interprocessor communication
+ * over a set of supported transport (Shared Memory, UART, BAM, HSIC)
+ *
+ * All ports preserve message boundaries across the interprocessor channel; one
+ * write into the port exactly matches one read from the port.
+ */
+/*@{*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "glink_os_utils.h"
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+
+/*================= RESTRICTED API ==========================*/
+/** Note that these API are only supported for RPM client. No other
+ * client may use these as a generic API as the underlying implementation
+ * works only for RPM ports */
+
+
+/**
+ * This API allows the RPM client to poll the transport for any new data
+ * that might have come in. It would *usually* be used when incoming interrupts
+ * are disabled.
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_rpm_rx_poll
+(
+ glink_handle_type handle
+);
+
+/**
+ * This API allows the RPM client to mask/unmask rx interrupts
+ *
+ * @param[in] handle GLink handle associated with the logical channel
+ *
+ * @param[in] mask Whether to mask or un-mask the incoming interrupt
+ *
+ * @param[in] platform_struct Any platform specific into that transport may
+ require
+ *
+ * @return Standard GLink error codes
+ *
+ * @sideeffects None
+ */
+glink_err_type glink_rpm_mask_rx_interrupt
+(
+ glink_handle_type handle,
+ boolean mask,
+ void *platform_struct
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //GLINK_RPM_H
+
diff --git a/platform/msm_shared/include/glink_transport_if.h b/platform/msm_shared/include/glink_transport_if.h
new file mode 100644
index 0000000..da9e2bd
--- /dev/null
+++ b/platform/msm_shared/include/glink_transport_if.h
@@ -0,0 +1,353 @@
+/* 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.
+*/
+
+#ifndef GLINK_TRANSPORT_IF_H
+#define GLINK_TRANSPORT_IF_H
+
+/**
+ * @file glink_transport_if.h
+ *
+ * Public API for the GLink Core to transport interface
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+#include <smem_list.h>
+#include <glink_os_utils.h>
+
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+/* GLink transport capability bit definitions */
+/* Whether transport supports signalling */
+#define GLINK_CAPABILITY_SIG_SUPPORT 0x00000001
+/* Intentless mode of operation */
+#define GLINK_CAPABILITY_INTENTLESS 0x00000002
+
+/*===========================================================================
+ TYPE DECLARATIONS
+===========================================================================*/
+/* forward declaration */
+struct glink_transport_if;
+typedef struct glink_transport_if glink_transport_if_type;
+
+struct glink_core_xport_ctx;
+typedef struct glink_core_xport_ctx glink_core_xport_ctx_type;
+
+struct glink_core_if;
+typedef struct glink_core_if glink_core_if_type;
+
+struct glink_rx_intent;
+typedef struct glink_rx_intent glink_rx_intent_type;
+
+/* Priority of transports registered with glink */
+typedef enum {
+ GLINK_XPORT_SMEM = 100,
+ GLINK_XPORT_RPM = 100,
+ GLINK_XPORT_SMD = 200,
+ GLINK_XPORT_CP_ENGINE = 300,
+ GLINK_MIN_PRIORITY = GLINK_XPORT_CP_ENGINE,
+ GLINK_INVALID_PRIORITY
+} glink_xport_priority;
+
+/** Glink core -> Xport pkt type definition */
+typedef struct {
+ void *data; /* Pointer to the data buffer to be transmitted */
+ const void *pkt_priv; /* Per packet private data */
+ uint32 iid; /* Remote intent ID being used to transmit data */
+ size_t size; /* Size of data buffer */
+ size_t size_remaining; /* Size left to transmit */
+ void *iovec; /* Pointer to the data buffer to be transmitted */
+ glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
+ glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
+}glink_core_tx_pkt_type;
+
+/** Transmit a version command for local negotiation. The transport would call
+ * glink_transport_if_type::rx_cmd_version_ack callback as a result */
+typedef void (*tx_cmd_version_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version, /* Version */
+ uint32 features /* Features */
+);
+
+/** Transmit a version ack for remote nogotiation */
+typedef void (*tx_cmd_version_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version, /* Version */
+ uint32 features /* Features */
+);
+
+/** Signals the negotiation is complete and transport can now do version
+ * specific initialization. Return uint32 transport capabilities bit field */
+typedef uint32 (*set_version_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 version, /* Version */
+ uint32 features /* Features */
+);
+
+/** Sends OPEN command to transport for transport to do whatever it deems
+ * necessary to open a GLink logical channel.
+ * GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be called
+ * as a result of channel opening. */
+typedef glink_err_type (*tx_cmd_ch_open_fn)
+(
+ glink_transport_if_type *if_ptr,/* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ const char *name, /* String name for the logical channel */
+ glink_xport_priority prio
+);
+
+/** Sends CLOSE command to transport for transport to do whatever it deems
+ * necessary to close the specified GLink logical channel.
+ * GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+ * called as a result of channel closing. */
+typedef glink_err_type (*tx_cmd_ch_close_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid /* Local channel ID */
+);
+
+/** Sends the remote open ACK command in response to receiving
+ * glink_core_if_type::rx_cmd_ch_remote_open */
+typedef void (*tx_cmd_ch_remote_open_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid, /* Remote channel ID */
+ glink_xport_priority prio
+);
+
+/** Sends the remote close ACK command in response to receiving
+ * glink_core_if_type::rx_cmd_ch_remote_close */
+typedef void (*tx_cmd_ch_remote_close_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 rcid /* Remote channel ID */
+);
+
+/** Allocates a receive buffer for the local rx intent */
+typedef glink_err_type (*allocate_rx_intent_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ size_t size, /* Size of Rx intent */
+ glink_rx_intent_type *intent_ptr /* Intent ptr */
+);
+
+/** Deallocates a receive buffer for the local rx intent */
+typedef glink_err_type (*deallocate_rx_intent_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ glink_rx_intent_type *intent_ptr /* Intent ptr */
+);
+
+/** Send receive intent ID for a given channel */
+typedef glink_err_type (*tx_cmd_local_rx_intent_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ size_t size, /* Size of Rx intent */
+ uint32 liid /* Local indent ID */
+);
+
+/** Send receive done command for an intent for the specified channel */
+typedef void(*tx_cmd_local_rx_done_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ uint32 liid, /* Local indent ID */
+ boolean reuse /* Reuse indent */
+);
+
+/** Send a data packet to the transport to be transmitted over the specified
+ * channel */
+typedef glink_err_type (*tx_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ glink_core_tx_pkt_type *pctx /* Packet to be transmitted */
+);
+
+/** Send a intent request to the remote side to have it queue more rx intents
+ * to unblock this end's tx operation */
+typedef glink_err_type (*tx_cmd_rx_intent_req_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ size_t size /* Size of the requested intent */
+);
+
+/** Send the ACK back for the rx intent request send by the other side,
+ * specifynig whether the request was granted ot not */
+typedef glink_err_type (*tx_cmd_remote_rx_intent_req_ack_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ boolean granted /* Whether of not the intent request was
+ granted */
+);
+
+/** Sets the local channel signals as per the specified 32-bit mask.
+ * Transport may also send the 32-bit value as-is to the remote side. */
+typedef glink_err_type (*tx_cmd_set_sigs_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ uint32 lcid, /* Local channel ID */
+ uint32 sigs /* Whether of not the intent request was
+ granted */
+);
+
+/** Lets the XAL know of SSR on that edge. */
+typedef glink_err_type (*ssr_fn)
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/** Trigger a poll for any rx data / signals on transport. */
+typedef glink_err_type (*poll_fn)
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+/** Mask/Unmask rx interrupt associated with transport. */
+typedef glink_err_type (*mask_rx_irq_fn)
+(
+ glink_transport_if_type *if_ptr, /* Pointer to the interface instance */
+ boolean mask /* TRUE-mask, FALSE=unmask */
+);
+
+/** Wait for the link to go down. */
+typedef boolean (*wait_link_down_fn)
+(
+ glink_transport_if_type *if_ptr /* Pointer to the interface instance */
+);
+
+
+/**
+ * Data Structure for GLink Core to call into transport API
+ *
+ * This structure is used by the GLink core to operate transport
+ * This set of function pointers to to be filled in by the transport
+ * abstraction layer.
+ */
+struct glink_transport_if {
+ /* Link needed for use with list APIs. Must be at the head of the struct */
+ smem_list_link_type link;
+
+ /** Transmit a version command for local negotiation. The transport would
+ * call glink_transport_if_type::rx_cmd_version_ack callback as a result */
+ tx_cmd_version_fn tx_cmd_version;
+
+ /** Transmit a version ack for remote nogotiation */
+ tx_cmd_version_ack_fn tx_cmd_version_ack;
+
+ /** Signals the negotiation is complete and transport can now do version
+ * specific initialization */
+ set_version_fn set_version;
+
+
+ /** Sends OPEN command to transport for transport to do whatever it deems
+ * necessary to open a GLink logical channel.
+ * GLink Core expects glink_transport_if_type::rx_cmd_ch_open_ack to be
+ * called as a result of channel opening. */
+ tx_cmd_ch_open_fn tx_cmd_ch_open;
+
+
+ /** Sends CLOSE command to transport for transport to do whatever it deems
+ * necessary to close the specified GLink logical channel.
+ * GLink Core expects glink_transport_if_type::rx_cmd_ch_close_ack to be
+ * called as a result of channel closing. */
+ tx_cmd_ch_close_fn tx_cmd_ch_close;
+
+
+ /** Sends the remote open ACK command in response to receiving
+ * glink_core_if_type::rx_cmd_ch_remote_open */
+ tx_cmd_ch_remote_open_ack_fn tx_cmd_ch_remote_open_ack;
+
+ /** Sends the remote close ACK command in response to receiving
+ * glink_core_if_type::rx_cmd_ch_remote_close */
+ tx_cmd_ch_remote_close_ack_fn tx_cmd_ch_remote_close_ack;
+
+ /** Allocates a receive vector buffer for the local rx intent */
+ allocate_rx_intent_fn allocate_rx_intent;
+
+ /** Deallocates a receive vector buffer for the local rx intent */
+ deallocate_rx_intent_fn deallocate_rx_intent;
+
+ /** Send receive intent ID for a given channel */
+ tx_cmd_local_rx_intent_fn tx_cmd_local_rx_intent;
+
+
+ /** Send receive done command for an intent for the specified channel */
+ tx_cmd_local_rx_done_fn tx_cmd_local_rx_done;
+
+
+ /** Send a data packet to the transport to be transmitted over the specified
+ * channel */
+ tx_fn tx;
+
+ /** Send request to the remote to queue more rx intents */
+ tx_cmd_rx_intent_req_fn tx_cmd_rx_intent_req;
+
+ /** Send ACK to the remote side's request to queue more rx intents */
+ tx_cmd_remote_rx_intent_req_ack_fn tx_cmd_remote_rx_intent_req_ack;
+
+ /** Sets the local channel signals as per the specified 32-bit mask.
+ * Transport may also send the 32-bit value as-is to the remote side. */
+ tx_cmd_set_sigs_fn tx_cmd_set_sigs;
+
+ /** Lets the XAL know of SSR on that edge. */
+ ssr_fn ssr;
+
+ /** Trigger a poll for any rx data / signals on transport. */
+ poll_fn poll;
+
+ /** Mask/Unmask rx interrupt associated with transport */
+ mask_rx_irq_fn mask_rx_irq;
+
+ /** Wait for the link to go down. */
+ wait_link_down_fn wait_link_down;
+
+ /** Transport specific data pointer that transport may choose fill in
+ * with some data */
+ glink_core_xport_ctx_type *glink_core_priv;
+
+ /** GLINK core interface pointer associated with this transport interface */
+ glink_core_if_type *glink_core_if_ptr;
+
+ /* glink transport priority */
+ glink_xport_priority glink_priority;
+};
+
+#endif //GLINK_TRANSPORT_IF_H
diff --git a/platform/msm_shared/include/glink_vector.h b/platform/msm_shared/include/glink_vector.h
new file mode 100644
index 0000000..863c19a
--- /dev/null
+++ b/platform/msm_shared/include/glink_vector.h
@@ -0,0 +1,155 @@
+/* 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.
+*/
+
+#ifndef GLINK_VECTOR_H
+#define GLINK_VECTOR_H
+
+/*===========================================================================
+
+ GLink Vector Header File
+
+===========================================================================*/
+
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+#include "glink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================
+ FEATURE DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ MACRO DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+typedef struct _glink_iovector_element_type {
+ struct _glink_iovector_element_type *next;
+ void* data;
+ size_t start_offset;
+ size_t size;
+} glink_iovector_element_type;
+
+typedef struct _glink_iovector_type {
+ glink_iovector_element_type *vlist; /* virtual buffers list */
+ glink_iovector_element_type *vlast; /* last accessed element in vlist */
+ glink_iovector_element_type *plist; /* physical buffers list */
+ glink_iovector_element_type *plast; /* last accessed element in plist */
+} glink_iovector_type;
+
+/*===========================================================================
+ GLOBAL DATA DECLARATIONS
+===========================================================================*/
+
+/*===========================================================================
+ LOCAL FUNCTION DEFINITIONS
+===========================================================================*/
+
+/*===========================================================================
+ EXTERNAL FUNCTION DEFINITIONS
+===========================================================================*/
+/*===========================================================================
+FUNCTION glink_dummy_tx_vprovider
+===========================================================================*/
+/**
+
+ Buffer provider for virtual space that operates on a non-vectored buffer.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return virtual address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_dummy_tx_vprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+);
+
+/*===========================================================================
+FUNCTION glink_dummy_rx_vprovider
+===========================================================================*/
+/**
+
+ Buffer provider for virtual space that operates on a Glink iovec.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return virtual address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_iovec_vprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+);
+
+/*===========================================================================
+FUNCTION glink_dummy_rx_pprovider
+===========================================================================*/
+/**
+
+ Buffer provider for physical space that operates on a Glink iovec.
+
+ @param[in] iovec Pointer to the dummy vector.
+ @param[in] offset Offset within the dummy vector.
+ @param[out] size Size of the provied buffer.
+
+ @return physical address of the buffer.
+
+ @sideeffects None.
+*/
+/*=========================================================================*/
+void* glink_iovec_pprovider
+(
+ void* iovec,
+ size_t offset,
+ size_t *size
+);
+
+#endif /* GLINK_VECTOR_H */
diff --git a/platform/msm_shared/include/smem_list.h b/platform/msm_shared/include/smem_list.h
new file mode 100644
index 0000000..22148cb
--- /dev/null
+++ b/platform/msm_shared/include/smem_list.h
@@ -0,0 +1,214 @@
+/* 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.
+*/
+
+#ifndef SMEM_LIST_H
+#define SMEM_LIST_H
+
+/**
+ * @file smem_list.h
+ *
+ * Public data types and functions to implement a generic
+ * list.
+ */
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup smem
+@{ */
+
+
+/*===========================================================================
+
+ TYPE DEFINITIONS
+
+===========================================================================*/
+
+/** Defines the structure to link to the SMEM list */
+typedef struct smem_list_link
+{
+ struct smem_list_link *next;
+} smem_list_link_type;
+
+
+/** Defines the generic SMEM list type */
+typedef struct smem_list
+{
+ smem_list_link_type *next;
+ long count;
+} smem_list_type;
+
+/*===========================================================================
+
+ PUBLIC FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION smem_list_init
+===========================================================================*/
+/**
+ Creates a generic list.
+
+ @param[in/out] list Pointer to the user list.
+
+ @return
+ N/A.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION smem_list_append
+===========================================================================*/
+/**
+ Appends an element to the end of a generic list.
+
+ The element must contain a smem_list_link_type at its base address.
+ The element should not be already present in any list.
+
+ @param[in/out] list Pointer to the user list.
+ @param[in] item Element to be inserted.
+
+ @return
+ N/A.
+
+ @dependencies
+ The element must contain a smem_list_link_type at its base address.
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION smem_list_delete
+===========================================================================*/
+/**
+ Removes the specified element from a generic list.
+
+ The element may be present at any point in the list.
+
+ @param[in] list Pointer to the user list.
+ @param[in] item Element to be removed.
+
+ @return
+ 0 if the element is deleted, or a negative error code if the element
+ is not found.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item );
+
+/*===========================================================================
+FUNCTION smem_list_first
+===========================================================================*/
+/**
+ Retrieves the first element in the list without removing it.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Pointer to the first element in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list );
+
+/*===========================================================================
+FUNCTION smem_list_next
+===========================================================================*/
+/**
+ Retrieves the next element in the list.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Pointer to the next element in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item );
+
+/*===========================================================================
+FUNCTION smem_list_count
+===========================================================================*/
+/**
+ Gets the number of elements in the list.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Count of elements in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list );
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_LIST_H */
diff --git a/platform/msm_shared/include/smem_type.h b/platform/msm_shared/include/smem_type.h
new file mode 100644
index 0000000..17a2bb0
--- /dev/null
+++ b/platform/msm_shared/include/smem_type.h
@@ -0,0 +1,237 @@
+/* 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.
+*/
+
+#ifndef SMEM_TYPE_H
+#define SMEM_TYPE_H
+
+/**
+ * @file smem_type.h
+ *
+ * Public data types used by SMEM
+ */
+
+/** @addtogroup smem
+@{ */
+
+/*===========================================================================
+ TYPE DEFINITIONS
+===========================================================================*/
+/******************************************************************************
+ The most significant two bytes of this number are the smem major version and
+ the least significant two bytes are the smem minor version. The major version
+ number should be updated whenever a change which causes an incompatibility is
+ introduced.
+ The minor version number can track API changes and deprecations that will
+ not affect remote processors. This may include changes to the smem_mem_type
+ enum, if dependencies have already been satisfied on the relevant processors.
+ Inconsistencies in minor version, between processors, will not prevent smem
+ from booting, but major version inconsistencies will.
+ 0x2XXX in the minor version indicates that it is the SMEM minor version, and
+ unrelated to proc comm, which no longer exists.
+******************************************************************************/
+#define SMEM_VERSION_ID 0x000B2002
+
+#define SMEM_MAJOR_VERSION_MASK 0xFFFF0000
+#define SMEM_MINOR_VERSION_MASK 0x0000FFFF
+#define SMEM_FULL_VERSION_MASK 0xFFFFFFFF
+
+#define SMEM_NUM_SMD_CHANNELS 64
+#define SMEM_NUM_SMP2P_EDGES 8
+
+/** Types of memory that can be requested via smem_alloc.
+
+ All of these types of memory have corresponding buffers allocated in
+ smem_data_decl. If a buffer is added to smem_data_decl, add a corresponding
+ entry to this list.
+
+ SMEM_VERSION_FIRST and SMEM_VERSION_LAST are the first and last
+ boundaries for external version checking via the smem_version_set routine.
+ To set up versioning for a shared item, add an entry between
+ SMEM_VERSION_FIRST and SMEM_VERSION_LAST and update the SMEM version in
+ smem_version.h.
+
+ SMEM_VERSION_LAST need not be the last item in the enum.
+*/
+typedef enum
+{
+ SMEM_MEM_FIRST,
+ SMEM_RESERVED_PROC_COMM = SMEM_MEM_FIRST,
+ SMEM_FIRST_FIXED_BUFFER = SMEM_RESERVED_PROC_COMM,
+ SMEM_HEAP_INFO,
+ SMEM_ALLOCATION_TABLE,
+ SMEM_VERSION_INFO,
+ SMEM_HW_RESET_DETECT,
+ SMEM_RESERVED_AARM_WARM_BOOT,
+ SMEM_DIAG_ERR_MESSAGE,
+ SMEM_SPINLOCK_ARRAY,
+ SMEM_MEMORY_BARRIER_LOCATION,
+ SMEM_LAST_FIXED_BUFFER = SMEM_MEMORY_BARRIER_LOCATION,
+ SMEM_AARM_PARTITION_TABLE,
+ SMEM_AARM_BAD_BLOCK_TABLE,
+ SMEM_RESERVE_BAD_BLOCKS,
+ SMEM_RESERVED_WM_UUID,
+ SMEM_CHANNEL_ALLOC_TBL,
+ SMEM_SMD_BASE_ID,
+ SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_CHANNELS,
+ SMEM_SMEM_LOG_EVENTS,
+ SMEM_RESERVED_SMEM_STATIC_LOG_IDX,
+ SMEM_RESERVED_SMEM_STATIC_LOG_EVENTS,
+ SMEM_RESERVED_SMEM_SLOW_CLOCK_SYNC,
+ SMEM_RESERVED_SMEM_SLOW_CLOCK_VALUE,
+ SMEM_RESERVED_BIO_LED_BUF,
+ SMEM_SMSM_SHARED_STATE,
+ SMEM_RESERVED_SMSM_INT_INFO,
+ SMEM_RESERVED_SMSM_SLEEP_DELAY,
+ SMEM_RESERVED_SMSM_LIMIT_SLEEP,
+ SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED,
+ SMEM_APPS_POWER_STATUS = SMEM_RESERVED_SLEEP_POWER_COLLAPSE_DISABLED, /*APSS power status*/
+ SMEM_RESERVED_KEYPAD_KEYS_PRESSED,
+ SMEM_RESERVED_KEYPAD_STATE_UPDATED,
+ SMEM_RESERVED_KEYPAD_STATE_IDX,
+ SMEM_RESERVED_GPIO_INT,
+ SMEM_RESERVED_MDDI_LCD_IDX,
+ SMEM_RESERVED_MDDI_HOST_DRIVER_STATE,
+ SMEM_RESERVED_MDDI_LCD_DISP_STATE,
+ SMEM_RESERVED_LCD_CUR_PANEL,
+ SMEM_RESERVED_MARM_BOOT_SEGMENT_INFO,
+ SMEM_RESERVED_AARM_BOOT_SEGMENT_INFO,
+ SMEM_RESERVED_SLEEP_STATIC,
+ SMEM_RESERVED_SCORPION_FREQUENCY,
+ SMEM_RESERVED_SMD_PROFILES,
+ SMEM_RESERVED_TSSC_BUSY,
+ SMEM_RESERVED_HS_SUSPEND_FILTER_INFO,
+ SMEM_RESERVED_BATT_INFO,
+ SMEM_RESERVED_APPS_BOOT_MODE,
+ SMEM_VERSION_FIRST,
+ SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
+ SMEM_VERSION_SMD_BRIDGE,
+ SMEM_VERSION_SMSM,
+ SMEM_VERSION_SMD_NWAY_LOOP,
+ SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
+ SMEM_RESERVED_OSS_RRCASN1_BUF1,
+ SMEM_RESERVED_OSS_RRCASN1_BUF2,
+ SMEM_ID_VENDOR0,
+ SMEM_ID_VENDOR1,
+ SMEM_ID_VENDOR2,
+ SMEM_HW_SW_BUILD_ID,
+ SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID,
+ SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP =
+ SMEM_RESERVED_SMD_BLOCK_PORT_BASE_ID +
+ SMEM_NUM_SMD_CHANNELS,
+ SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP =
+ SMEM_RESERVED_SMD_BLOCK_PORT_PROC0_HEAP +
+ SMEM_NUM_SMD_CHANNELS,
+ SMEM_I2C_MUTEX = SMEM_RESERVED_SMD_BLOCK_PORT_PROC1_HEAP +
+ SMEM_NUM_SMD_CHANNELS,
+ SMEM_SCLK_CONVERSION,
+ SMEM_RESERVED_SMD_SMSM_INTR_MUX,
+ SMEM_SMSM_CPU_INTR_MASK,
+ SMEM_RESERVED_APPS_DEM_SLAVE_DATA,
+ SMEM_RESERVED_QDSP6_DEM_SLAVE_DATA,
+ SMEM_RESERVED_CLKREGIM_BSP,
+ SMEM_RESERVED_CLKREGIM_SOURCES,
+ SMEM_SMD_FIFO_BASE_ID,
+ SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
+ SMEM_NUM_SMD_CHANNELS,
+ SMEM_POWER_ON_STATUS_INFO,
+ SMEM_DAL_AREA,
+ SMEM_SMEM_LOG_POWER_IDX,
+ SMEM_SMEM_LOG_POWER_WRAP,
+ SMEM_SMEM_LOG_POWER_EVENTS,
+ SMEM_ERR_CRASH_LOG,
+ SMEM_ERR_F3_TRACE_LOG,
+ SMEM_SMD_BRIDGE_ALLOC_TABLE,
+ SMEM_SMD_FEATURE_SET,
+ SMEM_RESERVED_SD_IMG_UPGRADE_STATUS,
+ SMEM_SEFS_INFO,
+ SMEM_RESERVED_RESET_LOG,
+ SMEM_RESERVED_RESET_LOG_SYMBOLS,
+ SMEM_MODEM_SW_BUILD_ID,
+ SMEM_SMEM_LOG_MPROC_WRAP,
+ SMEM_RESERVED_BOOT_INFO_FOR_APPS,
+ SMEM_SMSM_SIZE_INFO,
+ SMEM_SMD_LOOPBACK_REGISTER,
+ SMEM_SSR_REASON_MSS0,
+ SMEM_SSR_REASON_WCNSS0,
+ SMEM_SSR_REASON_LPASS0,
+ SMEM_SSR_REASON_DSPS0,
+ SMEM_SSR_REASON_VCODEC0,
+ SMEM_VOICE,
+ SMEM_ID_SMP2P_BASE_APPS, /* = 427 */
+ SMEM_ID_SMP2P_BASE_MODEM = SMEM_ID_SMP2P_BASE_APPS +
+ SMEM_NUM_SMP2P_EDGES, /* = 435 */
+ SMEM_ID_SMP2P_BASE_ADSP = SMEM_ID_SMP2P_BASE_MODEM +
+ SMEM_NUM_SMP2P_EDGES, /* = 443 */
+ SMEM_ID_SMP2P_BASE_WCN = SMEM_ID_SMP2P_BASE_ADSP +
+ SMEM_NUM_SMP2P_EDGES, /* = 451 */
+ SMEM_ID_SMP2P_BASE_RPM = SMEM_ID_SMP2P_BASE_WCN +
+ SMEM_NUM_SMP2P_EDGES, /* = 459 */
+ SMEM_FLASH_DEVICE_INFO = SMEM_ID_SMP2P_BASE_RPM +
+ SMEM_NUM_SMP2P_EDGES, /* = 467 */
+ SMEM_BAM_PIPE_MEMORY, /* = 468 */
+ SMEM_IMAGE_VERSION_TABLE, /* = 469 */
+ SMEM_LC_DEBUGGER, /* = 470 */
+ SMEM_FLASH_NAND_DEV_INFO, /* =471 */
+ SMEM_A2_BAM_DESCRIPTOR_FIFO, /* = 472 */
+ SMEM_CPR_CONFIG, /* = 473 */
+ SMEM_CLOCK_INFO, /* = 474 */
+ SMEM_IPC_INFO, /* = 475 */
+ SMEM_RF_EEPROM_DATA, /* = 476 */
+ SMEM_COEX_MDM_WCN, /* = 477 */
+ SMEM_GLINK_NATIVE_XPORT_DESCRIPTOR, /* = 478 */
+ SMEM_GLINK_NATIVE_XPORT_FIFO_0, /* = 479 */
+ SMEM_GLINK_NATIVE_XPORT_FIFO_1, /* = 480 */
+
+ SMEM_MEM_LAST = SMEM_GLINK_NATIVE_XPORT_FIFO_1,
+ SMEM_INVALID
+} smem_mem_type;
+
+/**
+ * A list of hosts supported in SMEM
+*/
+typedef enum
+{
+ SMEM_APPS = 0, /**< Apps Processor */
+ SMEM_MODEM = 1, /**< Modem processor */
+ SMEM_ADSP = 2, /**< ADSP processor */
+ SMEM_RSVD3 = 3, /**< Reserved */
+ SMEM_WCN = 4, /**< WCN processor */
+ SMEM_RSVD5 = 5, /**< Reserved */
+ SMEM_RPM = 6, /**< RPM processor */
+ SMEM_NUM_HOSTS = 7, /**< Max number of host in target */
+ SMEM_INVALID_HOST, /**< Invalid processor */
+
+ SMEM_Q6 = SMEM_ADSP, /**< Kept for legacy purposes.
+ ** New code should use SMEM_ADSP */
+ SMEM_RIVA = SMEM_WCN, /**< Kept for legacy purposes.
+ ** New code should use SMEM_WCN */
+}smem_host_type;
+
+/** @} */ /* end_addtogroup smem */
+
+#endif /* SMEM_TYPE_H */
diff --git a/platform/msm_shared/include/xport_rpm.h b/platform/msm_shared/include/xport_rpm.h
new file mode 100644
index 0000000..2566172
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm.h
@@ -0,0 +1,85 @@
+/* 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.
+*/
+
+#ifndef XPORT_RPM_H
+#define XPORT_RPM_H
+
+/**
+ * @file xport_rpm.h
+ *
+ * Internal definitions for RPM Glink transport
+ */
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+#include "glink_transport_if.h"
+#include <glink.h>
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+
+/* Version request command */
+#define XPORT_RPM_CMD_VERSION_REQ 0x0
+/* Version ACK command */
+#define XPORT_RPM_CMD_VERSION_ACK 0x1
+/* Open channel command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL 0x2
+/* Close channel command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL 0x3
+/* Open channel ACK command */
+#define XPORT_RPM_CMD_OPEN_CHANNEL_ACK 0x4
+/* Tx data command */
+#define XPORT_RPM_CMD_TX_DATA 0x9
+/* Close channel ACK command */
+#define XPORT_RPM_CMD_CLOSE_CHANNEL_ACK 0xB
+/* Tx signals command */
+#define XPORT_RPM_CMD_TX_SIGNALS 0xF
+
+
+#define XPORT_RPM_GET_CMD_ID(c) ((c) & 0xFFFF)
+#define XPORT_RPM_SET_CMD_ID(cmd_id) ((cmd_id) & 0xFFFF)
+
+#define XPORT_RPM_GET_CHANNEL_ID(c) (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_CHANNEL_ID(cid) (((cid) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_STR_LEN(c) (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_STR_LEN(c) (((c) << 16) & 0xFFFF0000)
+#define XPORT_RPM_GET_PRIO(c) ((c) & 0xFFFF)
+#define XPORT_RPM_SET_PRIO(c) ((c) & 0xFFFF)
+
+#define XPORT_RPM_GET_VERSION(c) (((c) >> 16) & 0xFFFF)
+#define XPORT_RPM_SET_VERSION(v) (((v) << 16) & 0xFFFF0000)
+
+
+/*===========================================================================
+ TYPE DECLARATIONS
+===========================================================================*/
+
+glink_err_type xport_rpm_init(void *arg);
+#endif //XPORT_RPM_H
+
diff --git a/platform/msm_shared/include/xport_rpm_config.h b/platform/msm_shared/include/xport_rpm_config.h
new file mode 100644
index 0000000..e0e24dd
--- /dev/null
+++ b/platform/msm_shared/include/xport_rpm_config.h
@@ -0,0 +1,97 @@
+/* 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.
+*/
+
+#ifndef XPORT_RPM_CONFIG_H
+#define XPORT_RPM_CONFIG_H
+
+/**
+ * @file xport_rpm_config.h
+ *
+ * Internal definitions for RPM Glink transport configurations
+ */
+
+/*===========================================================================
+ INCLUDE FILES
+===========================================================================*/
+#include "glink.h"
+#include "glink_os_utils.h"
+#include "smem_type.h"
+
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+#define XPORT_RPM_TOC_MAGIC 0x67727430
+
+#define XPORT_RPM_AP2R_ID 0x61703272
+#define XPORT_RPM_R2AP_ID 0x72326170
+#define XPORT_RPM_MP2R_ID 0x6D703272
+#define XPORT_RPM_R2MP_ID 0x72326D70
+#define XPORT_RPM_AD2R_ID 0x61643272
+#define XPORT_RPM_R2AD_ID 0x72326164
+#define XPORT_RPM_SC2R_ID 0x73633272
+#define XPORT_RPM_R2SC_ID 0x72327363
+#define XPORT_RPM_WC2R_ID 0x77633272
+#define XPORT_RPM_R2WC_ID 0x72327763
+#define XPORT_RPM_TZ2R_ID 0x747A3272
+#define XPORT_RPM_R2TZ_ID 0x7232747A
+
+#define XPORT_RPM_TOC_MAGIC_IDX 0
+#define XPORT_RPM_TOC_LENGTH_IDX 1
+#define XPORT_RPM_TOC_ENTRIES_IDX 2
+
+#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
+
+/*===========================================================================
+ TYPE DECLARATIONS
+===========================================================================*/
+typedef struct _xport_rpm_toc_entry_type
+{
+ uint32 fifo_id; /* FIFO ID */
+ uint32 fifo_offset; /* FIFO offset in MSG RAM */
+ uint32 fifo_size; /* FIFO size */
+} xport_rpm_toc_entry_type;
+
+typedef struct _xport_rpm_toc_config_type
+{
+ uint32 fifo_id; /* FIFO ID */
+ smem_host_type host; /* Host ID for MSG RAM allocation */
+ uint32 fifo_size; /* FIFO size */
+} xport_rpm_toc_config_type;
+
+
+typedef struct _xport_rpm_config_type
+{
+ const char* remote_ss; /* Remote host name */
+ uint32 tx_fifo_id; /* Tx FIFO ID in RPM ToC */
+ uint32 rx_fifo_id; /* Rx FIFO ID in RPM ToC */
+ os_ipc_intr_type irq_out; /* Outgoing interrupt */
+ uint32 irq_in; /* Incoming interrupt */
+} xport_rpm_config_type;
+
+#endif //XPORT_RPM_CONFIG_H
+
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 793b88c..5ea6402 100755
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -43,6 +43,19 @@
$(LOCAL_DIR)/boot_verifier.o
endif
+ifeq ($(ENABLE_GLINK_SUPPORT),1)
+OBJS += \
+ $(LOCAL_DIR)/glink/glink_api.o \
+ $(LOCAL_DIR)/glink/glink_core_if.o \
+ $(LOCAL_DIR)/glink/glink_rpmcore_setup.o \
+ $(LOCAL_DIR)/glink/glink_core_intentless_xport.o \
+ $(LOCAL_DIR)/glink/glink_os_utils_dal.o \
+ $(LOCAL_DIR)/glink/glink_vector.o \
+ $(LOCAL_DIR)/glink/xport_rpm.o \
+ $(LOCAL_DIR)/glink/xport_rpm_config.o \
+ $(LOCAL_DIR)/smem_list.o
+endif
+
ifeq ($(PLATFORM),msm8x60)
OBJS += $(LOCAL_DIR)/mipi_dsi.o \
$(LOCAL_DIR)/i2c_qup.o \
diff --git a/platform/msm_shared/smem_list.c b/platform/msm_shared/smem_list.c
new file mode 100644
index 0000000..fc89671
--- /dev/null
+++ b/platform/msm_shared/smem_list.c
@@ -0,0 +1,242 @@
+/* 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.
+*/
+
+/*===========================================================================
+
+ S H A R E D M E M O R Y
+
+===========================================================================*/
+
+
+
+/*===========================================================================
+
+ INCLUDE FILES
+
+===========================================================================*/
+#include "smem_list.h"
+#include <sys/types.h>
+
+/*=============================================================================
+
+ GLOBAL DEFINITIONS AND DECLARATIONS FOR MODULE
+
+=============================================================================*/
+
+
+/*===========================================================================
+
+ PRIVATE FUNCTION DECLARATIONS
+
+===========================================================================*/
+
+/*===========================================================================
+FUNCTION smem_list_init
+===========================================================================*/
+/**
+ Creates a generic list.
+
+ @param[in/out] list Pointer to the user list.
+
+ @return
+ N/A.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void smem_list_init( smem_list_type *list )
+{
+ list->next = NULL;
+ list->count = 0;
+}
+
+/*===========================================================================
+FUNCTION smem_list_append
+===========================================================================*/
+/**
+ Appends an element to the end of a generic list.
+
+ The element must contain a smem_list_link_type at its base address.
+ The element should not be already present in any list.
+
+ @param[in/out] list Pointer to the user list.
+ @param[in] item Element to be inserted.
+
+ @return
+ N/A.
+
+ @dependencies
+ The element must contain a smem_list_link_type at its base address.
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void smem_list_append( smem_list_type *list, void *item )
+{
+ smem_list_link_type *link = ( smem_list_link_type * )list;
+
+ /* get next item until link->next points to null */
+ while( link->next )
+ {
+ link = link->next;
+ }
+
+ /* link->next points to null here, but we can point it to the new item */
+ link->next = item;
+
+ /* point link to the head of the new item */
+ link = item;
+
+ /* terminate the list */
+ link->next = NULL;
+
+ list->count++;
+}
+
+/*===========================================================================
+FUNCTION smem_list_delete
+===========================================================================*/
+/**
+ Removes the specified element from a generic list.
+
+ The element may be present at any point in the list.
+
+ @param[in] list Pointer to the user list.
+ @param[in] item Element to be removed.
+
+ @return
+ 0 if the element is deleted, or a negative error code if the element
+ is not found.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+long smem_list_delete( smem_list_type *list, void *item )
+{
+ smem_list_link_type *link = ( smem_list_link_type * )list;
+
+ /* get next item until link points to item in question */
+ while( link->next != item )
+ {
+ if( NULL == link->next )
+ {
+ return -1;
+ }
+
+ link = link->next;
+ }
+
+ link->next = ( ( smem_list_link_type * )item )->next;
+
+ list->count--;
+
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION smem_list_first
+===========================================================================*/
+/**
+ Retrieves the first element in the list without removing it.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Pointer to the first element in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void *smem_list_first( smem_list_type *list )
+{
+ /* return the first item in the list */
+ return list->next;
+}
+
+/*===========================================================================
+FUNCTION smem_list_next
+===========================================================================*/
+/**
+ Retrieves the next element in the list.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Pointer to the next element in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+void *smem_list_next( void * item )
+{
+ /* just return the item that this item points to
+ * (base address contains a pointer) */
+ return ( ( smem_list_link_type * )item )->next;
+}
+
+/*===========================================================================
+FUNCTION smem_list_count
+===========================================================================*/
+/**
+ Gets the number of elements in the list.
+
+ @param[in] list Pointer to the user list.
+
+ @return
+ Count of elements in the list.
+
+ @dependencies
+ List must be protected by critical sections for multi-threaded use.
+
+ @sideeffects
+ None.
+*/
+/*=========================================================================*/
+long smem_list_count( smem_list_type *list )
+{
+ return list->count;
+}
+