blob: e87a3dc6e57c289b835553ba66775b5eb563e0a0 [file] [log] [blame]
/* Copyright (c) 2014-2015, 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_XPRT_IF_H_
#define _SOC_QCOM_GLINK_XPRT_IF_H_
#include <linux/bitops.h>
#include <linux/list.h>
#include <linux/types.h>
struct glink_core_xprt_ctx;
struct glink_core_if;
struct channel_ctx;
struct glink_core_rx_intent;
enum buf_type {
LINEAR = 0,
VECTOR,
};
enum xprt_ids {
SMEM_XPRT_ID = 100,
SMD_TRANS_XPRT_ID = 200,
LLOOP_XPRT_ID = 300,
MOCK_XPRT_ID = 400,
};
#define GCAP_SIGNALS BIT(0)
#define GCAP_INTENTLESS BIT(1)
/**
* TX PKT info.
*/
struct glink_core_tx_pkt {
struct list_head list_node;
struct list_head list_done;
const void *pkt_priv;
const void *data;
uint32_t riid;
uint32_t size;
uint32_t size_remaining;
size_t intent_size;
void *iovec;
void * (*vprovider)(void *iovec, size_t offset, size_t *size);
void * (*pprovider)(void *iovec, size_t offset, size_t *size);
};
/**
* Note - each call to register the interface must pass a unique
* instance of this data.
*/
struct glink_transport_if {
/* Negotiation */
void (*tx_cmd_version)(struct glink_transport_if *if_ptr,
uint32_t version,
uint32_t features);
void (*tx_cmd_version_ack)(struct glink_transport_if *if_ptr,
uint32_t version,
uint32_t features);
uint32_t (*set_version)(struct glink_transport_if *if_ptr,
uint32_t version,
uint32_t features);
/* channel state */
int (*tx_cmd_ch_open)(struct glink_transport_if *if_ptr, uint32_t lcid,
const char *name, uint16_t req_xprt);
int (*tx_cmd_ch_close)(struct glink_transport_if *if_ptr,
uint32_t lcid);
void (*tx_cmd_ch_remote_open_ack)(struct glink_transport_if *if_ptr,
uint32_t rcid, uint16_t xprt_resp);
void (*tx_cmd_ch_remote_close_ack)(struct glink_transport_if *if_ptr,
uint32_t rcid);
int (*ssr)(struct glink_transport_if *if_ptr);
/* channel data */
int (*allocate_rx_intent)(struct glink_transport_if *if_ptr,
size_t size,
struct glink_core_rx_intent *intent);
int (*deallocate_rx_intent)(struct glink_transport_if *if_ptr,
struct glink_core_rx_intent *intent);
/* Optional */
int (*reuse_rx_intent)(struct glink_transport_if *if_ptr,
struct glink_core_rx_intent *intent);
int (*tx_cmd_local_rx_intent)(struct glink_transport_if *if_ptr,
uint32_t lcid, size_t size, uint32_t liid);
void (*tx_cmd_local_rx_done)(struct glink_transport_if *if_ptr,
uint32_t lcid, uint32_t liid, bool reuse);
int (*tx)(struct glink_transport_if *if_ptr, uint32_t lcid,
struct glink_core_tx_pkt *pctx);
int (*tx_cmd_rx_intent_req)(struct glink_transport_if *if_ptr,
uint32_t lcid, size_t size);
int (*tx_cmd_remote_rx_intent_req_ack)(
struct glink_transport_if *if_ptr,
uint32_t lcid, bool granted);
int (*tx_cmd_set_sigs)(struct glink_transport_if *if_ptr,
uint32_t lcid, uint32_t sigs);
/* Optional. If NULL at xprt registration, dummies will be used */
int (*poll)(struct glink_transport_if *if_ptr, uint32_t lcid);
int (*mask_rx_irq)(struct glink_transport_if *if_ptr, uint32_t lcid,
bool mask, void *pstruct);
int (*wait_link_down)(struct glink_transport_if *if_ptr);
/*
* Keep data pointers at the end of the structure after all function
* pointer to allow for in-place initialization.
*/
/* private pointer for core */
struct glink_core_xprt_ctx *glink_core_priv;
/* core pointer (set during transport registration) */
struct glink_core_if *glink_core_if_ptr;
};
#ifdef CONFIG_MSM_GLINK
/**
* get_tx_vaddr() - Get the virtual address from which the tx has to be done
* @pctx: transmit packet context.
* @offset: offset into the packet.
* @tx_size: pointer to hold the length of the contiguous buffer
* space.
*
* Return: Address from which the tx has to be done.
*/
static inline void *get_tx_vaddr(struct glink_core_tx_pkt *pctx, size_t offset,
size_t *tx_size)
{
void *pdata;
if (pctx->vprovider) {
return pctx->vprovider((void *)pctx->iovec, offset, tx_size);
} else if (pctx->pprovider) {
pdata = pctx->pprovider((void *)pctx->iovec, offset, tx_size);
return phys_to_virt((unsigned long)pdata);
}
return NULL;
}
/**
* glink_xprt_name_to_id() - convert transport name to id
* @name: Name of the transport.
* @id: Assigned id.
*
* Return: 0 on success or standard Linux error code.
*/
int glink_xprt_name_to_id(const char *name, uint16_t *id);
#else /* CONFIG_MSM_GLINK */
static inline void *get_tx_vaddr(struct glink_core_tx_pkt *pctx, size_t offset,
size_t *tx_size)
{
return NULL;
}
static inline int glink_xprt_name_to_id(const char *name, uint16_t *id)
{
return -ENODEV;
}
#endif /* CONFIG_MSM_GLINK */
#endif /* _SOC_QCOM_GLINK_XPRT_IF_H_ */