/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _SOC_QCOM_GLINK_CORE_IF_H_ #define _SOC_QCOM_GLINK_CORE_IF_H_ #include #include #include "glink_private.h" /* Local Channel state */ enum local_channel_state_e { GLINK_CHANNEL_CLOSED = 0, GLINK_CHANNEL_OPENING, GLINK_CHANNEL_OPENED, GLINK_CHANNEL_CLOSING, }; /* Transport Negotiation State */ enum transport_state_e { GLINK_XPRT_DOWN, GLINK_XPRT_NEGOTIATING, GLINK_XPRT_OPENED, GLINK_XPRT_FAILED, }; struct channel_ctx; struct glink_core_xprt_ctx; struct glink_transport_if; struct glink_core_version; /** * struct glink_core_version - Individual version element * * version: supported version * features: all supported features for version */ struct glink_core_version { uint32_t version; uint32_t features; uint32_t (*negotiate_features)(struct glink_transport_if *if_ptr, const struct glink_core_version *version_ptr, uint32_t features); }; /** * RX intent * * data: pointer to the data (may be NULL for zero-copy) * id: remote or local intent ID * pkt_size: total size of packet * write_offset: next write offset (initially 0) * intent_size: size of the original intent (do not modify) * tracer_pkt: Flag to indicate if the data is a tracer packet * iovec: Pointer to vector buffer if the transport passes a vector buffer * vprovider: Virtual address-space buffer provider for a vector buffer * pprovider: Physical address-space buffer provider for a vector buffer * cookie: Private transport specific cookie * pkt_priv: G-Link core owned packet-private data * list: G-Link core owned list node * bounce_buf: Pointer to the temporary/internal bounce buffer */ struct glink_core_rx_intent { void *data; uint32_t id; size_t pkt_size; size_t write_offset; size_t intent_size; bool tracer_pkt; void *iovec; void * (*vprovider)(void *iovec, size_t offset, size_t *size); void * (*pprovider)(void *iovec, size_t offset, size_t *size); void *cookie; /* G-Link-Core-owned elements - please ignore */ struct list_head list; const void *pkt_priv; void *bounce_buf; }; /** * struct glink_core_flow_info - Flow specific Information * @mtu_tx_time_us: Time to transmit an MTU in microseconds. * @power_state: Power state associated with the traffic flow. */ struct glink_core_flow_info { unsigned long mtu_tx_time_us; uint32_t power_state; }; /** * struct glink_core_transport_cfg - configuration of a new transport * @name: Name of the transport. * @edge: Subsystem the transport connects to. * @versions: Array of transport versions supported. * @versions_entries: Number of entries in @versions. * @max_cid: Maximum number of channel identifiers supported. * @max_iid: Maximum number of intent identifiers supported. * @mtu: MTU supported by this transport. * @num_flows: Number of traffic flows/priority buckets. * @flow_info: Information about each flow/priority. * @token_count: Number of tokens per assignment. */ struct glink_core_transport_cfg { const char *name; const char *edge; const struct glink_core_version *versions; size_t versions_entries; uint32_t max_cid; uint32_t max_iid; size_t mtu; uint32_t num_flows; struct glink_core_flow_info *flow_info; uint32_t token_count; }; struct glink_core_if { /* Negotiation */ void (*link_up)(struct glink_transport_if *if_ptr); void (*link_down)(struct glink_transport_if *if_ptr); void (*rx_cmd_version)(struct glink_transport_if *if_ptr, uint32_t version, uint32_t features); void (*rx_cmd_version_ack)(struct glink_transport_if *if_ptr, uint32_t version, uint32_t features); /* channel management */ void (*rx_cmd_ch_remote_open)(struct glink_transport_if *if_ptr, uint32_t rcid, const char *name, uint16_t req_xprt); void (*rx_cmd_ch_open_ack)(struct glink_transport_if *if_ptr, uint32_t lcid, uint16_t xprt_resp); void (*rx_cmd_ch_remote_close)(struct glink_transport_if *if_ptr, uint32_t rcid); void (*rx_cmd_ch_close_ack)(struct glink_transport_if *if_ptr, uint32_t lcid); /* channel data */ struct glink_core_rx_intent * (*rx_get_pkt_ctx)( struct glink_transport_if *if_ptr, uint32_t rcid, uint32_t liid); void (*rx_put_pkt_ctx)(struct glink_transport_if *if_ptr, uint32_t rcid, struct glink_core_rx_intent *intent_ptr, bool complete); void (*rx_cmd_remote_rx_intent_put)(struct glink_transport_if *if_ptr, uint32_t rcid, uint32_t riid, size_t size); void (*rx_cmd_remote_rx_intent_put_cookie)( struct glink_transport_if *if_ptr, uint32_t rcid, uint32_t riid, size_t size, void *cookie); void (*rx_cmd_tx_done)(struct glink_transport_if *if_ptr, uint32_t rcid, uint32_t riid, bool reuse); void (*rx_cmd_remote_rx_intent_req)(struct glink_transport_if *if_ptr, uint32_t rcid, size_t size); void (*rx_cmd_rx_intent_req_ack)(struct glink_transport_if *if_ptr, uint32_t rcid, bool granted); void (*rx_cmd_remote_sigs)(struct glink_transport_if *if_ptr, uint32_t rcid, uint32_t sigs); /* channel scheduling */ void (*tx_resume)(struct glink_transport_if *if_ptr); }; int glink_core_register_transport(struct glink_transport_if *if_ptr, struct glink_core_transport_cfg *cfg); void glink_core_unregister_transport(struct glink_transport_if *if_ptr); /** * of_get_glink_core_qos_cfg() - Parse the qos related dt entries * @phandle: The handle to the qos related node in DT. * @cfg: The transport configuration to be filled. * * Return: 0 on Success, standard Linux error otherwise. */ int of_get_glink_core_qos_cfg(struct device_node *phandle, struct glink_core_transport_cfg *cfg); /** * rx_linear_vbuf_provider() - Virtual Buffer Provider for linear buffers * iovec: Pointer to the beginning of the linear buffer. * offset: Offset into the buffer whose address is needed. * size: Pointer to hold the length of the contiguous buffer space. * * This function is used when a linear buffer is received while the client has * registered to receive vector buffers. * * Return: Address of the buffer which is at offset "offset" from the beginning * of the buffer. */ static inline void *rx_linear_vbuf_provider(void *iovec, size_t offset, size_t *size) { struct glink_core_rx_intent *rx_info = (struct glink_core_rx_intent *)iovec; if (unlikely(!iovec || !size)) return NULL; if (unlikely(offset >= rx_info->pkt_size)) return NULL; if (unlikely(OVERFLOW_ADD_UNSIGNED(void *, rx_info->data, offset))) return NULL; *size = rx_info->pkt_size - offset; return rx_info->data + offset; } #endif /* _SOC_QCOM_GLINK_CORE_IF_H_ */