blob: 704171fdbf34ed4c07a4866566dcf3c802431d9c [file] [log] [blame]
/* Copyright (c) 2014-2017, 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 <linux/of.h>
#include <linux/types.h>
#include <linux/sched.h>
#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.
* @tx_task: Task structure for tx thread.
* @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;
struct task_struct *tx_task;
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_ */