diff options
author | Karthikeyan Ramasubramanian <kramasub@codeaurora.org> | 2016-02-03 14:20:26 -0700 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:08:08 -0700 |
commit | cdb2ce4239f547fe7c680f875a07dcb7dd39c3a7 (patch) | |
tree | e6d784b7fafa72cb84a82d4bc5d4e4da44cc2851 /include | |
parent | 7c45a7bcfa99ef68330b208566955e64221331de (diff) |
soc: qcom: Add snapshot of QMI
This snapshot is taken as of msm-3.18 commit e70ad0cd (Promotion of
kernel.lnx.3.18-151201.)
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/qmi_encdec.h | 184 | ||||
-rw-r--r-- | include/soc/qcom/msm_qmi_interface.h | 501 |
2 files changed, 685 insertions, 0 deletions
diff --git a/include/linux/qmi_encdec.h b/include/linux/qmi_encdec.h new file mode 100644 index 000000000000..66c3d84485ed --- /dev/null +++ b/include/linux/qmi_encdec.h @@ -0,0 +1,184 @@ +/* Copyright (c) 2012-2014, 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 _QMI_ENCDEC_H_ +#define _QMI_ENCDEC_H_ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/mm.h> +#include <linux/list.h> +#include <linux/socket.h> +#include <linux/gfp.h> + +#define QMI_REQUEST_CONTROL_FLAG 0x00 +#define QMI_RESPONSE_CONTROL_FLAG 0x02 +#define QMI_INDICATION_CONTROL_FLAG 0x04 +#define QMI_HEADER_SIZE 7 + +/** + * elem_type - Enum to identify the data type of elements in a data + * structure. + */ +enum elem_type { + QMI_OPT_FLAG = 1, + QMI_DATA_LEN, + QMI_UNSIGNED_1_BYTE, + QMI_UNSIGNED_2_BYTE, + QMI_UNSIGNED_4_BYTE, + QMI_UNSIGNED_8_BYTE, + QMI_SIGNED_2_BYTE_ENUM, + QMI_SIGNED_4_BYTE_ENUM, + QMI_STRUCT, + QMI_STRING, + QMI_EOTI, +}; + +/** + * array_type - Enum to identify if an element in a data structure is + * an array. If so, then is it a static length array or a + * variable length array. + */ +enum array_type { + NO_ARRAY = 0, + STATIC_ARRAY = 1, + VAR_LEN_ARRAY = 2, +}; + +/** + * elem_info - Data structure to specify information about an element + * in a data structure. An array of this data structure + * can be used to specify info about a complex data + * structure to be encoded/decoded. + * + * @data_type: Data type of this element. + * @elem_len: Array length of this element, if an array. + * @elem_size: Size of a single instance of this data type. + * @is_array: Array type of this element. + * @tlv_type: QMI message specific type to identify which element + * is present in an incoming message. + * @offset: To identify the address of the first instance of this + * element in the data structure. + * @ei_array: Array to provide information about the nested structure + * within a data structure to be encoded/decoded. + */ +struct elem_info { + enum elem_type data_type; + uint32_t elem_len; + uint32_t elem_size; + enum array_type is_array; + uint8_t tlv_type; + uint32_t offset; + struct elem_info *ei_array; +}; + +/** + * @msg_desc - Describe about the main/outer structure to be + * encoded/decoded. + * + * @max_msg_len: Maximum possible length of the QMI message. + * @ei_array: Array to provide information about a data structure. + */ +struct msg_desc { + uint16_t msg_id; + int max_msg_len; + struct elem_info *ei_array; +}; + +struct qmi_header { + unsigned char cntl_flag; + uint16_t txn_id; + uint16_t msg_id; + uint16_t msg_len; +} __attribute__((__packed__)); + +static inline void encode_qmi_header(unsigned char *buf, + unsigned char cntl_flag, uint16_t txn_id, + uint16_t msg_id, uint16_t msg_len) +{ + struct qmi_header *hdr = (struct qmi_header *)buf; + + hdr->cntl_flag = cntl_flag; + hdr->txn_id = txn_id; + hdr->msg_id = msg_id; + hdr->msg_len = msg_len; +} + +static inline void decode_qmi_header(unsigned char *buf, + unsigned char *cntl_flag, uint16_t *txn_id, + uint16_t *msg_id, uint16_t *msg_len) +{ + struct qmi_header *hdr = (struct qmi_header *)buf; + + *cntl_flag = hdr->cntl_flag; + *txn_id = hdr->txn_id; + *msg_id = hdr->msg_id; + *msg_len = hdr->msg_len; +} + +#ifdef CONFIG_QMI_ENCDEC +/** + * qmi_kernel_encode() - Encode to QMI message wire format + * @desc: Pointer to structure descriptor. + * @out_buf: Buffer to hold the encoded QMI message. + * @out_buf_len: Length of the out buffer. + * @in_c_struct: C Structure to be encoded. + * + * @return: size of encoded message on success, < 0 on error. + */ +int qmi_kernel_encode(struct msg_desc *desc, + void *out_buf, uint32_t out_buf_len, + void *in_c_struct); + +/** + * qmi_kernel_decode() - Decode to C Structure format + * @desc: Pointer to structure descriptor. + * @out_c_struct: Buffer to hold the decoded C structure. + * @in_buf: Buffer containg the QMI message to be decoded. + * @in_buf_len: Length of the incoming QMI message. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct, + void *in_buf, uint32_t in_buf_len); + +/** + * qmi_verify_max_msg_len() - Verify the maximum length of a QMI message + * @desc: Pointer to structure descriptor. + * + * @return: true if the maximum message length embedded in structure + * descriptor matches the calculated value, else false. + */ +bool qmi_verify_max_msg_len(struct msg_desc *desc); + +#else +static inline int qmi_kernel_encode(struct msg_desc *desc, + void *out_buf, uint32_t out_buf_len, + void *in_c_struct) +{ + return -EOPNOTSUPP; +} + +static inline int qmi_kernel_decode(struct msg_desc *desc, + void *out_c_struct, + void *in_buf, uint32_t in_buf_len) +{ + return -EOPNOTSUPP; +} + +static inline bool qmi_verify_max_msg_len(struct msg_desc *desc) +{ + return false; +} +#endif + +#endif diff --git a/include/soc/qcom/msm_qmi_interface.h b/include/soc/qcom/msm_qmi_interface.h new file mode 100644 index 000000000000..135265b74991 --- /dev/null +++ b/include/soc/qcom/msm_qmi_interface.h @@ -0,0 +1,501 @@ +/* Copyright (c) 2012-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 _MSM_QMI_INTERFACE_H_ +#define _MSM_QMI_INTERFACE_H_ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/mm.h> +#include <linux/list.h> +#include <linux/socket.h> +#include <linux/gfp.h> +#include <linux/qmi_encdec.h> +#include <linux/workqueue.h> + +#define QMI_COMMON_TLV_TYPE 0 + +enum qmi_event_type { + QMI_RECV_MSG = 1, + QMI_SERVER_ARRIVE, + QMI_SERVER_EXIT, +}; + +/** + * struct qmi_handle - QMI Handle Data Structure + * @handle_hash: Hash Table Node in which this handle is present. + * @src_port: Pointer to port used for message exchange. + * @ctl_port: Pointer to port used for out-of-band event exchange. + * @handle_type: Type of handle(Service/Client). + * @next_txn_id: Transaction ID of the next outgoing request. + * @handle_wq: Workqueue to handle any handle-specific events. + * @handle_lock: Lock to protect access to elements in the handle. + * @notify_lock: Lock to protect and generate notification atomically. + * @notify: Function to notify the handle owner of an event. + * @notify_priv: Private info to be passed during the notifcation. + * @handle_reset: Flag to hold the reset state of the handle. + * @reset_waitq: Wait queue to wait for any reset events. + * @ctl_work: Work to handle the out-of-band events for this handle. + * @dest_info: Destination to which this handle is connected to. + * @dest_service_id: service id of the service that client connected to. + * @txn_list: List of transactions waiting for the response. + * @ind_cb: Function to notify the handle owner of an indication message. + * @ind_cb_priv: Private info to be passed during an indication notification. + * @resume_tx_work: Work to resume the tx when the transport is not busy. + * @pending_txn_list: List of requests pending tx due to busy transport. + * @conn_list: List of connections handled by the service. + * @svc_ops_options: Service specific operations and options. + */ +struct qmi_handle { + struct hlist_node handle_hash; + void *src_port; + void *ctl_port; + unsigned handle_type; + uint16_t next_txn_id; + struct workqueue_struct *handle_wq; + struct mutex handle_lock; + spinlock_t notify_lock; + void (*notify)(struct qmi_handle *handle, enum qmi_event_type event, + void *notify_priv); + void *notify_priv; + int handle_reset; + wait_queue_head_t reset_waitq; + struct delayed_work ctl_work; + + /* Client specific elements */ + void *dest_info; + uint32_t dest_service_id; + struct list_head txn_list; + void (*ind_cb)(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + unsigned int msg_len, void *ind_cb_priv); + void *ind_cb_priv; + struct delayed_work resume_tx_work; + struct list_head pending_txn_list; + + /* Service specific elements */ + struct list_head conn_list; + struct qmi_svc_ops_options *svc_ops_options; +}; + +enum qmi_result_type_v01 { + /* To force a 32 bit signed enum. Do not change or use*/ + QMI_RESULT_TYPE_MIN_ENUM_VAL_V01 = INT_MIN, + QMI_RESULT_SUCCESS_V01 = 0, + QMI_RESULT_FAILURE_V01 = 1, + QMI_RESULT_TYPE_MAX_ENUM_VAL_V01 = INT_MAX, +}; + +enum qmi_error_type_v01 { + /* To force a 32 bit signed enum. Do not change or use*/ + QMI_ERR_TYPE_MIN_ENUM_VAL_V01 = INT_MIN, + QMI_ERR_NONE_V01 = 0x0000, + QMI_ERR_MALFORMED_MSG_V01 = 0x0001, + QMI_ERR_NO_MEMORY_V01 = 0x0002, + QMI_ERR_INTERNAL_V01 = 0x0003, + QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 = 0x0005, + QMI_ERR_INVALID_ID_V01 = 0x0029, + QMI_ERR_ENCODING_V01 = 0x003A, + QMI_ERR_INCOMPATIBLE_STATE_V01 = 0x005A, + QMI_ERR_NOT_SUPPORTED_V01 = 0x005E, + QMI_ERR_TYPE_MAX_ENUM_VAL_V01 = INT_MAX, +}; + +struct qmi_response_type_v01 { + enum qmi_result_type_v01 result; + enum qmi_error_type_v01 error; +}; + +/** + * qmi_svc_ops_options - Operations and options to be specified when + * a service registers. + * @version: Version field to identify the ops_options structure. + * @service_id: Service ID of the service. + * @service_vers: Version to identify the client-service compatibility. + * @service_ins: Instance ID registered by the service. + * @connect_cb: Callback when a new client connects with the service. + * @disconnect_cb: Callback when the client exits the connection. + * @req_desc_cb: Callback to get request structure and its descriptor + * for a message id. + * @req_cb: Callback to process the request. + */ +struct qmi_svc_ops_options { + unsigned version; + uint32_t service_id; + uint32_t service_vers; + uint32_t service_ins; + int (*connect_cb)(struct qmi_handle *handle, + void *conn_handle); + int (*disconnect_cb)(struct qmi_handle *handle, + void *conn_handle); + int (*req_desc_cb)(unsigned int msg_id, + struct msg_desc **req_desc); + int (*req_cb)(struct qmi_handle *handle, + void *conn_handle, + void *req_handle, + unsigned int msg_id, + void *req); +}; + +#ifdef CONFIG_MSM_QMI_INTERFACE + +/* Element info array describing common qmi response structure */ +extern struct elem_info qmi_response_type_v01_ei[]; +#define get_qmi_response_type_v01_ei() qmi_response_type_v01_ei + +/** + * qmi_handle_create() - Create a QMI handle + * @notify: Callback to notify events on the handle created. + * @notify_priv: Private information to be passed along with the notification. + * + * @return: Valid QMI handle on success, NULL on error. + */ +struct qmi_handle *qmi_handle_create( + void (*notify)(struct qmi_handle *handle, + enum qmi_event_type event, void *notify_priv), + void *notify_priv); + +/** + * qmi_handle_destroy() - Destroy the QMI handle + * @handle: QMI handle to be destroyed. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_handle_destroy(struct qmi_handle *handle); + +/** + * qmi_register_ind_cb() - Register the indication callback function + * @handle: QMI handle with which the function is registered. + * @ind_cb: Callback function to be registered. + * @ind_cb_priv: Private data to be passed with the indication callback. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_register_ind_cb(struct qmi_handle *handle, + void (*ind_cb)(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + unsigned int msg_len, void *ind_cb_priv), + void *ind_cb_priv); + +/** + * qmi_send_req_wait() - Send a synchronous QMI request + * @handle: QMI handle through which the QMI request is sent. + * @request_desc: Structure describing the request data structure. + * @req: Buffer containing the request data structure. + * @req_len: Length of the request data structure. + * @resp_desc: Structure describing the response data structure. + * @resp: Buffer to hold the response data structure. + * @resp_len: Length of the response data structure. + * @timeout_ms: Timeout before a response is received. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_req_wait(struct qmi_handle *handle, + struct msg_desc *req_desc, + void *req, unsigned int req_len, + struct msg_desc *resp_desc, + void *resp, unsigned int resp_len, + unsigned long timeout_ms); + +/** + * qmi_send_req_nowait() - Send an asynchronous QMI request + * @handle: QMI handle through which the QMI request is sent. + * @request_desc: Structure describing the request data structure. + * @req: Buffer containing the request data structure. + * @req_len: Length of the request data structure. + * @resp_desc: Structure describing the response data structure. + * @resp: Buffer to hold the response data structure. + * @resp_len: Length of the response data structure. + * @resp_cb: Callback function to be invoked when the response arrives. + * @resp_cb_data: Private information to be passed along with the callback. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_req_nowait(struct qmi_handle *handle, + struct msg_desc *req_desc, + void *req, unsigned int req_len, + struct msg_desc *resp_desc, + void *resp, unsigned int resp_len, + void (*resp_cb)(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + void *resp_cb_data, + int stat), + void *resp_cb_data); + +/** + * qmi_recv_msg() - Receive the QMI message + * @handle: Handle for which the QMI message has to be received. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_recv_msg(struct qmi_handle *handle); + +/** + * qmi_connect_to_service() - Connect the QMI handle with a QMI service + * @handle: QMI handle to be connected with the QMI service. + * @service_id: Service id to identify the QMI service. + * @service_vers: Version to identify the compatibility. + * @service_ins: Instance id to identify the instance of the QMI service. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_connect_to_service(struct qmi_handle *handle, + uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins); + +/** + * qmi_svc_event_notifier_register() - Register a notifier block to receive + * events regarding a QMI service + * @service_id: Service ID to identify the QMI service. + * @service_vers: Version to identify the compatibility. + * @service_ins: Instance ID to identify the instance of the QMI service. + * @nb: Notifier block used to receive the event. + * + * @return: 0 if successfully registered, < 0 on error. + */ +int qmi_svc_event_notifier_register(uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins, + struct notifier_block *nb); + +/** + * qmi_svc_event_notifier_unregister() - Unregister service event + * notifier block + * @service_id: Service ID to identify the QMI service. + * @service_vers: Version to identify the compatibility. + * @service_ins: Instance ID to identify the instance of the QMI service. + * @nb: Notifier block registered to receive the events. + * + * @return: 0 if successfully registered, < 0 on error. + */ +int qmi_svc_event_notifier_unregister(uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins, + struct notifier_block *nb); + +/** + * qmi_svc_register() - Register a QMI service with a QMI handle + * @handle: QMI handle on which the service has to be registered. + * @ops_options: Service specific operations and options. + * + * @return: 0 if successfully registered, < 0 on error. + */ +int qmi_svc_register(struct qmi_handle *handle, + void *ops_options); + +/** + * qmi_send_resp() - Send response to a request + * @handle: QMI handle from which the response is sent. + * @clnt: Client to which the response is sent. + * @req_handle: Request for which the response is sent. + * @resp_desc: Descriptor explaining the response structure. + * @resp: Pointer to the response structure. + * @resp_len: Length of the response structure. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_resp(struct qmi_handle *handle, + void *conn_handle, + void *req_handle, + struct msg_desc *resp_desc, + void *resp, + unsigned int resp_len); + +/** + * qmi_send_resp_from_cb() - Send response to a request from request_cb + * @handle: QMI handle from which the response is sent. + * @clnt: Client to which the response is sent. + * @req_handle: Request for which the response is sent. + * @resp_desc: Descriptor explaining the response structure. + * @resp: Pointer to the response structure. + * @resp_len: Length of the response structure. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_resp_from_cb(struct qmi_handle *handle, + void *conn_handle, + void *req_handle, + struct msg_desc *resp_desc, + void *resp, + unsigned int resp_len); + +/** + * qmi_send_ind() - Send unsolicited event/indication to a client + * @handle: QMI handle from which the indication is sent. + * @clnt: Client to which the indication is sent. + * @ind_desc: Descriptor explaining the indication structure. + * @ind: Pointer to the indication structure. + * @ind_len: Length of the indication structure. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_ind(struct qmi_handle *handle, + void *conn_handle, + struct msg_desc *ind_desc, + void *ind, + unsigned int ind_len); + +/** + * qmi_send_ind_from_cb() - Send indication to a client from registration_cb + * @handle: QMI handle from which the indication is sent. + * @clnt: Client to which the indication is sent. + * @ind_desc: Descriptor explaining the indication structure. + * @ind: Pointer to the indication structure. + * @ind_len: Length of the indication structure. + * + * @return: 0 on success, < 0 on error. + */ +int qmi_send_ind_from_cb(struct qmi_handle *handle, + void *conn_handle, + struct msg_desc *ind_desc, + void *ind, + unsigned int ind_len); + +/** + * qmi_svc_unregister() - Unregister the service from a QMI handle + * @handle: QMI handle from which the service has to be unregistered. + * + * return: 0 on success, < 0 on error. + */ +int qmi_svc_unregister(struct qmi_handle *handle); + +#else + +#define get_qmi_response_type_v01_ei() NULL + +static inline struct qmi_handle *qmi_handle_create( + void (*notify)(struct qmi_handle *handle, + enum qmi_event_type event, void *notify_priv), + void *notify_priv) +{ + return NULL; +} + +static inline int qmi_handle_destroy(struct qmi_handle *handle) +{ + return -ENODEV; +} + +static inline int qmi_register_ind_cb(struct qmi_handle *handle, + void (*ind_cb)(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + unsigned int msg_len, void *ind_cb_priv), + void *ind_cb_priv) +{ + return -ENODEV; +} + +static inline int qmi_send_req_wait(struct qmi_handle *handle, + struct msg_desc *req_desc, + void *req, unsigned int req_len, + struct msg_desc *resp_desc, + void *resp, unsigned int resp_len, + unsigned long timeout_ms) +{ + return -ENODEV; +} + +static inline int qmi_send_req_nowait(struct qmi_handle *handle, + struct msg_desc *req_desc, + void *req, unsigned int req_len, + struct msg_desc *resp_desc, + void *resp, unsigned int resp_len, + void (*resp_cb)(struct qmi_handle *handle, + unsigned int msg_id, void *msg, + void *resp_cb_data), + void *resp_cb_data) +{ + return -ENODEV; +} + +static inline int qmi_recv_msg(struct qmi_handle *handle) +{ + return -ENODEV; +} + +static inline int qmi_connect_to_service(struct qmi_handle *handle, + uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins) +{ + return -ENODEV; +} + +static inline int qmi_svc_event_notifier_register(uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins, + struct notifier_block *nb) +{ + return -ENODEV; +} + +static inline int qmi_svc_event_notifier_unregister(uint32_t service_id, + uint32_t service_vers, + uint32_t service_ins, + struct notifier_block *nb) +{ + return -ENODEV; +} + +static inline int qmi_svc_register(struct qmi_handle *handle, + void *ops_options) +{ + return -ENODEV; +} + +static inline int qmi_send_resp(struct qmi_handle *handle, + void *conn_handle, + void *req_handle, + struct msg_desc *resp_desc, + void *resp, + unsigned int resp_len) +{ + return -ENODEV; +} + +static inline int qmi_send_resp_from_cb(struct qmi_handle *handle, + void *conn_handle, + void *req_handle, + struct msg_desc *resp_desc, + void *resp, + unsigned int resp_len) +{ + return -ENODEV; +} + +static inline int qmi_send_ind(struct qmi_handle *handle, + void *conn_handle, + struct msg_desc *ind_desc, + void *ind, + unsigned int ind_len) +{ + return -ENODEV; +} + +static inline int qmi_send_ind_from_cb(struct qmi_handle *handle, + void *conn_handle, + struct msg_desc *ind_desc, + void *ind, + unsigned int ind_len) +{ + return -ENODEV; +} + +static inline int qmi_svc_unregister(struct qmi_handle *handle) +{ + return -ENODEV; +} + +#endif + +#endif |