blob: fd4d6be58631cb7ca60c6b6dee412617badd4238 [file] [log] [blame]
/* 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
===========================================================================*/
/* Limit of the proportion of total QoS requests
=GLINK_QOS_RATE_LIMIT_COEFF_N / GLINK_QOS_RATE_LIMIT_COEFF_D
*/
#define GLINK_QOS_RATE_LIMIT_COEFF_N 7
#define GLINK_QOS_RATE_LIMIT_COEFF_D 10
/* Number of QoS tokens given at refill */
#define GLINK_QOS_TOKENS (10)
/* Number of QoS buckets */
#define GLINK_QOS_BUCKETS (1)
/*===========================================================================
TYPE DECLARATIONS
===========================================================================*/
typedef struct glink_core_version glink_core_version_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 */
boolean tracer_pkt; /* Specify if this intent is for tracer packet */
glink_buffer_provider_fn vprovider; /* Buffer provider for virtual space */
glink_buffer_provider_fn pprovider; /* Buffer provider for physical space */
};
/** Context of Tx activity for a transport */
typedef struct glink_tx_xport_ctx_s {
os_event_type event; /* Event to signal Tx thread */
os_cs_type tx_q_cs; /* Lock to protect Tx queue */
smem_list_type tx_q; /* Tx channel queue */
uint32 qos_rate_sum; /* Sum of rates of registered QoS requests */
} glink_tx_xport_ctx_type;
/** G-Link Local channel states */
typedef enum
{
/** Initial State before entering channel state machine */
GLINK_LOCAL_CH_INIT,
/** Local G-Link channel is fully closed */
GLINK_LOCAL_CH_CLOSED,
/** Local G-Link channel opened channel and waiting for ACK from remote */
GLINK_LOCAL_CH_OPENING,
/** Local G-Link channel is fully opened */
GLINK_LOCAL_CH_OPENED,
/** Local G-Link channel closed the channel and waiting for ACK from remote */
GLINK_LOCAL_CH_CLOSING
}glink_local_state_type;
/** G-Link Remote channel states */
typedef enum
{
/** Initial State before entering channel state machine */
GLINK_REMOTE_CH_INIT,
/** Remote G-Link channel is closed */
GLINK_REMOTE_CH_CLOSED,
/** Remote G-Link channel is opened */
GLINK_REMOTE_CH_OPENED,
/* Glink channel state when SSR is received from remote sub-system */
GLINK_REMOTE_CH_SSR_RESET,
/** G-Link channel is pending cleanup.
This state is used for deferred channel cleanup in case
it sits in Tx scheduler queue */
GLINK_REMOTE_CH_CLEANUP
}glink_remote_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 */
);
/** 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 */
);
/** 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 */
);
/** Channel submit pkt */
typedef glink_err_type(*channel_submit_pkt_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 */
const char *xport;
/* Remote subsystem name */
const char *remote_ss;
/** Keep track of version array index in use */
const glink_core_version_type *version_array;
/** Keep track of version array index in use */
int32 version_indx;
/* Keeps track of the current status of the transport */
glink_transport_status_type status;
/* critical section to change/access xport status
* automically */
os_cs_type status_cs;
/* Transport's capabilities */
uint32 xport_capabilities;
/* Max lcid */
uint32 max_lcid;
/* 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 and channel state of all
channels in that 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;
/* Context of Tx activity for a transport */
glink_tx_xport_ctx_type *tx_ctx;
/* 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;
/* channel submit pkt */
channel_submit_pkt_fn channel_submit_pkt;
};
/**
* 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;
/** 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;
/** 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