android_kernel_sony_sdm845/include/soc/qcom/glink.h
Chris Lew a9a78ae4bc soc: qcom: glink: Add new APIs to toggle RX thread priority
Low latency use cases are failing because glink RX thread to handle
the TX Done command is not being scheduled during high system load.
These new APIs allow clients to specify if they need the RX glink
thread to be Realtime

CRs-Fixed: 2050701
Change-Id: I6bd4023394e9ee617797826687f34abaee3fe65d
Signed-off-by: Chris Lew <clew@codeaurora.org>
2017-07-17 03:31:21 -07:00

459 lines
14 KiB
C

/* 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_H_
#define _SOC_QCOM_GLINK_H_
#include <linux/types.h>
/* Maximum size (including null) for channel, edge, or transport names */
#define GLINK_NAME_SIZE 32
/* Maximum packet size for TX and RX */
#define GLINK_MAX_PKT_SIZE SZ_1M
/**
* G-Link Port State Notification Values
*/
enum {
GLINK_CONNECTED,
GLINK_LOCAL_DISCONNECTED,
GLINK_REMOTE_DISCONNECTED,
};
/**
* G-Link Open Options
*
* Used to define the glink_open_config::options field which is passed into
* glink_open().
*/
enum {
GLINK_OPT_INITIAL_XPORT = BIT(0),
GLINK_OPT_RX_INTENT_NOTIF = BIT(1),
};
/**
* Open configuration.
*
* priv: Private data passed into user callbacks
* options: Open option flags
* rx_intent_req_timeout_ms: Timeout for requesting an RX intent, in
* milliseconds; if set to 0, timeout is infinite
* notify_rx: Receive notification function (required)
* notify_tx_done: Transmit-done notification function (required)
* notify_state: State-change notification (required)
* notify_rx_intent_req: Receive intent request (optional)
* notify_rxv: Receive notification function for vector buffers
* (required if notify_rx is not provided)
* notify_sig: Signal-change notification (optional)
* notify_rx_tracer_pkt: Receive notification for tracer packet
* notify_remote_rx_intent: Receive notification for remote-queued RX intent
*
* This structure is passed into the glink_open() call to setup
* configuration handles. All unused fields should be set to 0.
*
* The structure is copied internally before the call to glink_open() returns.
*/
struct glink_open_config {
void *priv;
uint32_t options;
const char *transport;
const char *edge;
const char *name;
unsigned int rx_intent_req_timeout_ms;
void (*notify_rx)(void *handle, const void *priv, const void *pkt_priv,
const void *ptr, size_t size);
void (*notify_tx_done)(void *handle, const void *priv,
const void *pkt_priv, const void *ptr);
void (*notify_state)(void *handle, const void *priv,
unsigned int event);
bool (*notify_rx_intent_req)(void *handle, const void *priv,
size_t req_size);
void (*notify_rxv)(void *handle, const void *priv, const void *pkt_priv,
void *iovec, size_t size,
void * (*vbuf_provider)(void *iovec, size_t offset,
size_t *size),
void * (*pbuf_provider)(void *iovec, size_t offset,
size_t *size));
void (*notify_rx_sigs)(void *handle, const void *priv,
uint32_t old_sigs, uint32_t new_sigs);
void (*notify_rx_abort)(void *handle, const void *priv,
const void *pkt_priv);
void (*notify_tx_abort)(void *handle, const void *priv,
const void *pkt_priv);
void (*notify_rx_tracer_pkt)(void *handle, const void *priv,
const void *pkt_priv, const void *ptr, size_t size);
void (*notify_remote_rx_intent)(void *handle, const void *priv,
size_t size);
};
enum glink_link_state {
GLINK_LINK_STATE_UP,
GLINK_LINK_STATE_DOWN,
};
/**
* Data structure containing information during Link State callback
* transport: String identifying the transport.
* edge: String identifying the edge.
* link_state: Link state(UP?DOWN).
*/
struct glink_link_state_cb_info {
const char *transport;
const char *edge;
enum glink_link_state link_state;
};
/**
* Data structure containing information for link state registration
* transport: String identifying the transport.
* edge: String identifying the edge.
* glink_link_state_notif_cb: Callback function used to pass the event.
*/
struct glink_link_info {
const char *transport;
const char *edge;
void (*glink_link_state_notif_cb)(
struct glink_link_state_cb_info *cb_info,
void *priv);
};
enum tx_flags {
GLINK_TX_REQ_INTENT = 0x1,
GLINK_TX_SINGLE_THREADED = 0x2,
GLINK_TX_TRACER_PKT = 0x4,
GLINK_TX_ATOMIC = 0x8,
};
#ifdef CONFIG_MSM_GLINK
/**
* Open GLINK channel.
*
* @cfg_ptr: Open configuration structure (the structure is copied before
* glink_open returns). All unused fields should be zero-filled.
*
* This should not be called from link state callback context by clients.
* It is recommended that client should invoke this function from their own
* thread.
*
* Return: Pointer to channel on success, PTR_ERR() with standard Linux
* error code on failure.
*/
void *glink_open(const struct glink_open_config *cfg_ptr);
/**
* glink_close() - Close a previously opened channel.
*
* @handle: handle to close
*
* Once the closing process has been completed, the GLINK_LOCAL_DISCONNECTED
* state event will be sent and the channel can be reopened.
*
* Return: 0 on success; -EINVAL for invalid handle, -EBUSY is close is
* already in progress, standard Linux Error code otherwise.
*/
int glink_close(void *handle);
/**
* glink_tx() - Transmit packet.
*
* @handle: handle returned by glink_open()
* @pkt_priv: opaque data value that will be returned to client with
* notify_tx_done notification
* @data: pointer to the data
* @size: size of data
* @tx_flags: Flags to specify transmit specific options
*
* Return: -EINVAL for invalid handle; -EBUSY if channel isn't ready for
* transmit operation (not fully opened); -EAGAIN if remote side
* has not provided a receive intent that is big enough.
*/
int glink_tx(void *handle, void *pkt_priv, void *data, size_t size,
uint32_t tx_flags);
/**
* glink_queue_rx_intent() - Register an intent to receive data.
*
* @handle: handle returned by glink_open()
* @pkt_priv: opaque data type that is returned when a packet is received
* size: maximum size of data to receive
*
* Return: 0 for success; standard Linux error code for failure case
*/
int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size);
/**
* glink_rx_intent_exists() - Check if an intent of size exists.
*
* @handle: handle returned by glink_open()
* @size: size of an intent to check or 0 for any intent
*
* Return: TRUE if an intent exists with greater than or equal to the size
* else FALSE
*/
bool glink_rx_intent_exists(void *handle, size_t size);
/**
* glink_rx_done() - Return receive buffer to remote side.
*
* @handle: handle returned by glink_open()
* @ptr: data pointer provided in the notify_rx() call
* @reuse: if true, receive intent is re-used
*
* Return: 0 for success; standard Linux error code for failure case
*/
int glink_rx_done(void *handle, const void *ptr, bool reuse);
/**
* glink_txv() - Transmit a packet in vector form.
*
* @handle: handle returned by glink_open()
* @pkt_priv: opaque data value that will be returned to client with
* notify_tx_done notification
* @iovec: pointer to the vector (must remain valid until notify_tx_done
* notification)
* @size: size of data/vector
* @vbuf_provider: Client provided helper function to iterate the vector
* in physical address space
* @pbuf_provider: Client provided helper function to iterate the vector
* in virtual address space
* @tx_flags: Flags to specify transmit specific options
*
* Return: -EINVAL for invalid handle; -EBUSY if channel isn't ready for
* transmit operation (not fully opened); -EAGAIN if remote side has
* not provided a receive intent that is big enough.
*/
int glink_txv(void *handle, void *pkt_priv,
void *iovec, size_t size,
void * (*vbuf_provider)(void *iovec, size_t offset, size_t *size),
void * (*pbuf_provider)(void *iovec, size_t offset, size_t *size),
uint32_t tx_flags);
/**
* glink_sigs_set() - Set the local signals for the GLINK channel
*
* @handle: handle returned by glink_open()
* @sigs: modified signal value
*
* Return: 0 for success; standard Linux error code for failure case
*/
int glink_sigs_set(void *handle, uint32_t sigs);
/**
* glink_sigs_local_get() - Get the local signals for the GLINK channel
*
* handle: handle returned by glink_open()
* sigs: Pointer to hold the signals
*
* Return: 0 for success; standard Linux error code for failure case
*/
int glink_sigs_local_get(void *handle, uint32_t *sigs);
/**
* glink_sigs_remote_get() - Get the Remote signals for the GLINK channel
*
* handle: handle returned by glink_open()
* sigs: Pointer to hold the signals
*
* Return: 0 for success; standard Linux error code for failure case
*/
int glink_sigs_remote_get(void *handle, uint32_t *sigs);
/**
* glink_register_link_state_cb() - Register for link state notification
* @link_info: Data structure containing the link identification and callback.
* @priv: Private information to be passed with the callback.
*
* This function is used to register a notifier to receive the updates about a
* link's/transport's state. This notifier needs to be registered first before
* an attempt to open a channel.
*
* Return: a reference to the notifier handle.
*/
void *glink_register_link_state_cb(struct glink_link_info *link_info,
void *priv);
/**
* glink_unregister_link_state_cb() - Unregister the link state notification
* notif_handle: Handle to be unregistered.
*
* This function is used to unregister a notifier to stop receiving the updates
* about a link's/transport's state.
*/
void glink_unregister_link_state_cb(void *notif_handle);
/**
* glink_qos_latency() - Register the latency QoS requirement
* @handle: Channel handle in which the latency is required.
* @latency_us: Latency requirement in units of micro-seconds.
* @pkt_size: Worst case packet size for which the latency is required.
*
* This function is used to register the latency requirement for a channel
* and ensures that the latency requirement for this channel is met without
* impacting the existing latency requirements of other channels.
*
* Return: 0 if QoS request is achievable, standard Linux error codes on error
*/
int glink_qos_latency(void *handle, unsigned long latency_us, size_t pkt_size);
/**
* glink_qos_cancel() - Cancel or unregister the QoS request
* @handle: Channel handle for which the QoS request is cancelled.
*
* This function is used to cancel/unregister the QoS requests for a channel.
*
* Return: 0 on success, standard Linux error codes on failure
*/
int glink_qos_cancel(void *handle);
/**
* glink_qos_start() - Start of the transmission requiring QoS
* @handle: Channel handle in which the transmit activity is performed.
*
* This function is called by the clients to indicate G-Link regarding the
* start of the transmission which requires a certain QoS. The clients
* must account for the QoS ramp time to ensure meeting the QoS.
*
* Return: 0 on success, standard Linux error codes on failure
*/
int glink_qos_start(void *handle);
/**
* glink_qos_get_ramp_time() - Get the QoS ramp time
* @handle: Channel handle for which the QoS ramp time is required.
* @pkt_size: Worst case packet size.
*
* This function is called by the clients to obtain the ramp time required
* to meet the QoS requirements.
*
* Return: QoS ramp time is returned in units of micro-seconds
*/
unsigned long glink_qos_get_ramp_time(void *handle, size_t pkt_size);
/**
* glink_start_rx_rt() - Vote for RT thread priority on RX.
* @handle: Channel handle for which transaction are occurring.
*
* Return: 0 on success, standard Linux error codes on failure
*/
int glink_start_rx_rt(void *handle);
/**
* glink_end_rx_rt() - Vote for RT thread priority on RX.
* @handle: Channel handle for which transaction are occurring.
*
* Return: 0 on success, standard Linux error codes on failure
*/
int glink_end_rx_rt(void *handle);
#else /* CONFIG_MSM_GLINK */
static inline void *glink_open(const struct glink_open_config *cfg_ptr)
{
return NULL;
}
static inline int glink_close(void *handle)
{
return -ENODEV;
}
static inline int glink_tx(void *handle, void *pkt_priv, void *data,
size_t size, uint32_t tx_flags)
{
return -ENODEV;
}
static inline int glink_queue_rx_intent(void *handle, const void *pkt_priv,
size_t size)
{
return -ENODEV;
}
static inline bool glink_rx_intent_exists(void *handle, size_t size)
{
return -ENODEV;
}
static inline int glink_rx_done(void *handle, const void *ptr, bool reuse)
{
return -ENODEV;
}
static inline int glink_txv(void *handle, void *pkt_priv,
void *iovec, size_t size,
void * (*vbuf_provider)(void *iovec, size_t offset, size_t *size),
void * (*pbuf_provider)(void *iovec, size_t offset, size_t *size),
uint32_t tx_flags)
{
return -ENODEV;
}
static inline int glink_sigs_set(void *handle, uint32_t sigs)
{
return -ENODEV;
}
static inline int glink_sigs_local_get(void *handle, uint32_t *sigs)
{
return -ENODEV;
}
static inline int glink_sigs_remote_get(void *handle, uint32_t *sigs)
{
return -ENODEV;
}
static inline void *glink_register_link_state_cb(
struct glink_link_info *link_info, void *priv)
{
return NULL;
}
static inline void glink_unregister_link_state_cb(void *notif_handle)
{
}
static inline int glink_qos_latency(void *handle, unsigned long latency_us,
size_t pkt_size)
{
return -ENODEV;
}
static inline int glink_qos_cancel(void *handle)
{
return -ENODEV;
}
static inline int glink_qos_start(void *handle)
{
return -ENODEV;
}
static inline unsigned long glink_qos_get_ramp_time(void *handle,
size_t pkt_size)
{
return 0;
}
static inline int glink_start_rx_rt(void *handle)
{
return -ENODEV;
}
static inline int glink_end_rx_rt(void *handle)
{
return -ENODEV;
}
#endif /* CONFIG_MSM_GLINK */
#endif /* _SOC_QCOM_GLINK_H_ */