浏览代码

qcacld-3.0: Add QMI files for WFDS service

Add initial version of QMI files that are used for
communication between WLAN host driver on APSS and
WiFi driver on LPASS.

Change-Id: If7352490d73457479e85958b90066f9c397bb310
CRs-Fixed: 3328378
Yeshwanth Sriram Guntuka 2 年之前
父节点
当前提交
c589e67a42

+ 13 - 1
Kbuild

@@ -2592,6 +2592,12 @@ ifeq ($(CONFIG_QMI_COMPONENT_ENABLE), y)
 WLAN_QMI_COMP_OBJS := $(QMI_COMP_CORE_DIR)/wlan_qmi_main.o \
 		 $(QMI_COMP_UCFG_DIR)/wlan_qmi_ucfg_api.o  \
 		 $(QMI_COMP_OS_IF_DIR)/os_if_qmi.o
+
+ifeq ($(CONFIG_QMI_WFDS), y)
+WLAN_QMI_COMP_OBJS += $(QMI_COMP_OS_IF_DIR)/os_if_qmi_wifi_driver_service_v01.o
+WLAN_QMI_COMP_OBJS += $(QMI_COMP_OS_IF_DIR)/os_if_qmi_wfds.o
+WLAN_QMI_COMP_OBJS += $(QMI_COMP_UCFG_DIR)/wlan_qmi_wfds_api.o
+endif
 endif
 
 $(call add-wlan-objs,qmi_comp,$(WLAN_QMI_COMP_OBJS))
@@ -4287,7 +4293,13 @@ cppflags-$(CONFIG_WLAN_TRACEPOINTS) += -DWLAN_TRACEPOINTS
 
 cppflags-$(CONFIG_QCACLD_FEATURE_SON) += -DFEATURE_PERPKT_INFO
 cppflags-$(CONFIG_QCACLD_FEATURE_SON) += -DQCA_ENHANCED_STATS_SUPPORT
-cppflags-$(CONFIG_QMI_COMPONENT_ENABLE) += -DQMI_COMPONENT_ENABLE
+
+ifeq ($(CONFIG_QMI_COMPONENT_ENABLE), y)
+cppflags-y += -DQMI_COMPONENT_ENABLE
+ifeq ($(CONFIG_QMI_WFDS), y)
+cppflags-y += -DQMI_WFDS
+endif
+endif
 
 ifdef CONFIG_MAX_LOGS_PER_SEC
 ccflags-y += -DWLAN_MAX_LOGS_PER_SEC=$(CONFIG_MAX_LOGS_PER_SEC)

+ 208 - 0
components/qmi/dispatcher/inc/wlan_qmi_public_struct.h

@@ -23,10 +23,218 @@
 #ifndef _WLAN_QMI_PUBLIC_STRUCT_H_
 #define _WLAN_QMI_PUBLIC_STRUCT_H_
 
+#include "qdf_status.h"
+#include <qdf_types.h>
+
+#ifdef QMI_WFDS
+#define QMI_WFDS_CE_MAX_SRNG 3
+#define QMI_WFDS_MEM_ARENA_MAX 8
+#define QMI_WFDS_PAGE_INFO_ARRAY_MAX_SIZE 255
+
+/**
+ * enum wlan_qmi_wfds_srng_dir - SRNG direction
+ * @QMI_WFDS_SRNG_SOURCE_RING: SRNG source ring
+ * @QMI_WFDS_SRNG_DESTINATION_RING: SRNG destination ring
+ */
+enum wlan_qmi_wfds_srng_dir {
+	QMI_WFDS_SRNG_SOURCE_RING = 0,
+	QMI_WFDS_SRNG_DESTINATION_RING = 1,
+};
+
+/**
+ * struct wlan_qmi_wfds_srng_info - SRNG information
+ * @ring_id: SRNG ring id
+ * @dir: SRNG direction
+ * @num_entries: number of entries in SRNG
+ * @entry_size: size of SRNG descriptor
+ * @ring_base_paddr: ring base physical address of SRNG
+ * @hp_paddr: HP physical address of SRNG
+ * @tp_paddr: TP physical address of SRNG
+ */
+struct wlan_qmi_wfds_srng_info {
+	uint8_t ring_id;
+	enum wlan_qmi_wfds_srng_dir dir;
+	uint32_t num_entries;
+	uint32_t entry_size;
+	uint64_t ring_base_paddr;
+	uint64_t hp_paddr;
+	uint64_t tp_paddr;
+};
+
+/**
+ * enum wlan_qmi_wfds_pipe_dir - pipe direction
+ * @QMI_WFDS_PIPEDIR_NONE: none pipe direction
+ * @QMI_WFDS_PIPEDIR_IN: target to host pipe direction
+ * @QMI_WFDS_PIPEDIR_OUT:  host to target pipe direction
+ */
+enum wlan_qmi_wfds_pipe_dir {
+	QMI_WFDS_PIPEDIR_NONE = 0,
+	QMI_WFDS_PIPEDIR_IN = 1,
+	QMI_WFDS_PIPEDIR_OUT = 2,
+};
+
+/**
+ * struct wlan_qmi_wfds_ce_info - CE information
+ * @ce_id: CE id
+ * @ce_dir: CE direction
+ * @srng_info: SRNG information
+ */
+struct wlan_qmi_wfds_ce_info {
+	uint8_t ce_id;
+	enum wlan_qmi_wfds_pipe_dir ce_dir;
+	struct wlan_qmi_wfds_srng_info srng_info;
+};
+
+/**
+ * struct wlan_qmi_wfds_config_req_msg - WFDS config request message
+ * @ce_info_len: size of ce_info with valid entries
+ * @ce_info: CE information array
+ * @rx_refill_ring: refill SRNG information
+ * @shadow_rdptr_mem_paddr: shadow read memory physical address
+ * @shadow_rdptr_mem_size:  shadow read memory size
+ * @shadow_wrptr_mem_paddr: shadow write memory physical address
+ * @shadow_wrptr_mem_size: shadow write memory size
+ * @rx_pkt_tlv_len: rx packet tlvs length
+ * @rx_rbm: return buffer manager for rx buffers
+ * @pcie_bar_pa: PCIe BAR physical address
+ * @pci_slot: PCIe slot
+ * @lpass_ep_id: LPASS data message service endpoint id
+ */
+struct wlan_qmi_wfds_config_req_msg {
+	uint32_t ce_info_len;
+	struct wlan_qmi_wfds_ce_info ce_info[QMI_WFDS_CE_MAX_SRNG];
+	struct wlan_qmi_wfds_srng_info rx_refill_ring;
+	uint64_t shadow_rdptr_mem_paddr;
+	uint64_t shadow_rdptr_mem_size;
+	uint64_t shadow_wrptr_mem_paddr;
+	uint64_t shadow_wrptr_mem_size;
+	uint32_t rx_pkt_tlv_len;
+	uint32_t rx_rbm;
+	uint64_t pcie_bar_pa;
+	uint32_t pci_slot;
+	uint32_t lpass_ep_id;
+};
+
+/**
+ * enum wlan_qmi_wfds_mem_arenas - Memory arenas
+ * @QMI_WFDS_MEM_ARENA_TX_BUFFERS: tx buffers memory arena
+ * @QMI_WFDS_MEM_ARENA_CE_TX_MSG_BUFFERS: ce tx message buffers memory arena
+ * @QMI_WFDS_MEM_ARENA_CE_RX_MSG_BUFFERS: ce rx message buffers memory arena
+ */
+enum wlan_qmi_wfds_mem_arenas {
+	QMI_WFDS_MEM_ARENA_TX_BUFFERS = 0,
+	QMI_WFDS_MEM_ARENA_CE_TX_MSG_BUFFERS = 1,
+	QMI_WFDS_MEM_ARENA_CE_RX_MSG_BUFFERS = 2,
+};
+
+/**
+ * struct wlan_qmi_wfds_mem_arena_info - Memory arena information
+ * @entry_size: entry size
+ * @num_entries: total number of entries required
+ */
+struct wlan_qmi_wfds_mem_arena_info {
+	uint16_t entry_size;
+	uint16_t num_entries;
+};
+
+/**
+ * struct wlan_qmi_wfds_mem_ind_msg - Memory indication message
+ * @mem_arena_info_len: number of valid entries in mem_arena_info array
+ * @mem_arena_info: memory arena information array
+ */
+struct wlan_qmi_wfds_mem_ind_msg {
+	uint32_t mem_arena_info_len;
+	struct wlan_qmi_wfds_mem_arena_info mem_arena_info[QMI_WFDS_MEM_ARENA_MAX];
+};
+
+/**
+ * struct wlan_qmi_wfds_mem_arena_page_info - Memory arena
+ *  page information
+ * @num_entries_per_page: number of entries per page
+ * @page_dma_addr_len: number of valid entries in page_dma_addr array
+ * @page_dma_addr: page dma address array
+ */
+struct wlan_qmi_wfds_mem_arena_page_info {
+	uint16_t num_entries_per_page;
+	uint32_t page_dma_addr_len;
+	uint64_t page_dma_addr[QMI_WFDS_PAGE_INFO_ARRAY_MAX_SIZE];
+};
+
+/**
+ * struct wlan_qmi_wfds_mem_req_msg - Memory request message
+ *  page information
+ * @mem_arena_page_info_len: number of valid entries in
+ *  mem_arena_page_info array
+ * @mem_arena_page_info: memory arena information
+ */
+struct wlan_qmi_wfds_mem_req_msg {
+	uint32_t mem_arena_page_info_len;
+	struct wlan_qmi_wfds_mem_arena_page_info mem_arena_page_info[QMI_WFDS_MEM_ARENA_MAX];
+};
+
+/**
+ * struct wlan_qmi_wfds_ipcc_info - IPCC information
+ * @ce_id: CE id
+ * @ipcc_trig_addr: IPCC trigger address
+ * @ipcc_trig_data: IPCC trigger data
+ */
+struct wlan_qmi_wfds_ipcc_info {
+	uint8_t ce_id;
+	uint64_t ipcc_trig_addr;
+	uint32_t ipcc_trig_data;
+};
+
+/**
+ * struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg - IPCC map and configure
+ *  indication message
+ * @ipcc_ce_info_len: number of valid entries in ipcc_ce_info array
+ * @ipcc_ce_info: IPCC information for CE
+ */
+struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg {
+	uint32_t ipcc_ce_info_len;
+	struct wlan_qmi_wfds_ipcc_info ipcc_ce_info[QMI_WFDS_CE_MAX_SRNG];
+};
+
+/**
+ * enum wlan_qmi_wfds_status - status
+ * @QMI_WFDS_STATUS_SUCCESS: success status
+ * @QMI_WFDS_STATUS_FAILURE: failure status
+ */
+enum wlan_qmi_wfds_status {
+	QMI_WFDS_STATUS_SUCCESS = 0,
+	QMI_WFDS_STATUS_FAILURE = 1,
+};
+
+/**
+ * struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg - IPCC map and configure
+ *  request message
+ * @status: IPCC configuration status
+ */
+struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg {
+	enum wlan_qmi_wfds_status status;
+};
+#endif
+
 /**
  * struct wlan_qmi_psoc_callbacks - struct containing callbacks
  *  to osif QMI APIs
+ * @qmi_wfds_init: Callback to initialize WFDS QMI handle
+ * @qmi_wfds_deinit: Callback to deinitialize WFDS QMI handle
+ * @qmi_wfds_send_config_msg: Callback to send WFDS configuration message
+ * @qmi_wfds_send_req_mem_msg: Callback to send WFDS request memory message
+ * @qmi_wfds_send_ipcc_map_n_cfg_msg: Callback to send WFDS IPCC map and
+ *  configure message
  */
 struct wlan_qmi_psoc_callbacks {
+#ifdef QMI_WFDS
+	QDF_STATUS (*qmi_wfds_init)(void);
+	void (*qmi_wfds_deinit)(void);
+	QDF_STATUS (*qmi_wfds_send_config_msg)(
+			struct wlan_qmi_wfds_config_req_msg *src_info);
+	QDF_STATUS (*qmi_wfds_send_req_mem_msg)(
+			struct wlan_qmi_wfds_mem_req_msg *src_info);
+	QDF_STATUS (*qmi_wfds_send_ipcc_map_n_cfg_msg)(
+			struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info);
+#endif
 };
 #endif

+ 113 - 0
components/qmi/dispatcher/inc/wlan_qmi_wfds_api.h

@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_qmi_wfds_api.h
+ *
+ * Contains QMI wrapper API declarations to connect and send messages to
+ * QMI WFDS server
+ */
+#ifndef _WLAN_QMI_WFDS_API_H_
+#define _WLAN_QMI_WFDS_API_H_
+
+#include "wlan_objmgr_psoc_obj.h"
+#include "wlan_qmi_public_struct.h"
+
+#ifdef QMI_WFDS
+/**
+ * wlan_qmi_wfds_init() - Initialize WFDS QMI client
+ * @psoc: PSOC handle
+ *
+ * Returns: QDF status
+ */
+QDF_STATUS wlan_qmi_wfds_init(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_qmi_wfds_deinit() - Deinitialize WFDS QMI client
+ * @psoc: PSOC handle
+ *
+ * Returns: None
+ */
+void wlan_qmi_wfds_deinit(struct wlan_objmgr_psoc *psoc);
+
+/*
+ * wlan_qmi_wfds_send_config_msg() - Send config message to QMI server
+ *  to QMI server
+ * @psoc: PSOC handle
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+wlan_qmi_wfds_send_config_msg(struct wlan_objmgr_psoc *psoc,
+			      struct wlan_qmi_wfds_config_req_msg *src_info);
+
+/*
+ * wlan_qmi_wfds_send_req_mem_msg() - Send Request Memory message to QMI server
+ * @psoc: PSOC handle
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+wlan_qmi_wfds_send_req_mem_msg(struct wlan_objmgr_psoc *psoc,
+			       struct wlan_qmi_wfds_mem_req_msg *src_info);
+
+/*
+ * wlan_qmi_wfds_ipcc_map_n_cfg_msg() - Send the IPCC map and configure message
+ *  to QMI server
+ * @psoc: PSOC handle
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+QDF_STATUS
+wlan_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_objmgr_psoc *psoc,
+			struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info);
+#else
+static inline
+QDF_STATUS wlan_qmi_wfds_init(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline
+void wlan_qmi_wfds_deinit(struct wlan_objmgr_psoc *psoc)
+{
+}
+
+static inline QDF_STATUS
+wlan_qmi_wfds_send_config_msg(struct wlan_objmgr_psoc *psoc,
+			      struct wlan_qmi_wfds_config_req_msg *src_info);
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline QDF_STATUS
+wlan_qmi_wfds_send_req_mem_msg(struct wlan_objmgr_psoc *psoc,
+			       struct wlan_qmi_wfds_mem_req_msg *src_info);
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
+static inline QDF_STATUS
+wlan_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_objmgr_psoc *psoc,
+			struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif
+#endif

+ 32 - 0
components/qmi/dispatcher/src/wlan_qmi_ucfg_api.c

@@ -79,6 +79,36 @@ QDF_STATUS ucfg_qmi_deinit(void)
 	return status;
 }
 
+#ifdef QMI_WFDS
+/**
+ * ucfg_qmi_wfds_register_os_if_callbacks() - API to register wfds os if
+ *  callbacks with QMI component
+ * @qmi_ctx: QMI component context
+ * @cb_obj: callback object
+ *
+ * Return: None
+ */
+static void
+ucfg_qmi_wfds_register_os_if_callbacks(struct wlan_qmi_psoc_context *qmi_ctx,
+				       struct wlan_qmi_psoc_callbacks *cb_obj)
+{
+	qmi_ctx->qmi_cbs.qmi_wfds_init = cb_obj->qmi_wfds_init;
+	qmi_ctx->qmi_cbs.qmi_wfds_deinit = cb_obj->qmi_wfds_deinit;
+	qmi_ctx->qmi_cbs.qmi_wfds_send_config_msg =
+				cb_obj->qmi_wfds_send_config_msg;
+	qmi_ctx->qmi_cbs.qmi_wfds_send_req_mem_msg =
+				cb_obj->qmi_wfds_send_req_mem_msg;
+	qmi_ctx->qmi_cbs.qmi_wfds_send_ipcc_map_n_cfg_msg =
+				cb_obj->qmi_wfds_send_ipcc_map_n_cfg_msg;
+}
+#else
+static inline void
+ucfg_qmi_wfds_register_os_if_callbacks(struct wlan_qmi_psoc_context *qmi_ctx,
+				       struct wlan_qmi_psoc_callbacks *cb_obj)
+{
+}
+#endif
+
 void ucfg_qmi_register_os_if_callbacks(struct wlan_objmgr_psoc *psoc,
 				       struct wlan_qmi_psoc_callbacks *cb_obj)
 {
@@ -88,4 +118,6 @@ void ucfg_qmi_register_os_if_callbacks(struct wlan_objmgr_psoc *psoc,
 		qmi_err("QMI context is NULL");
 		return;
 	}
+
+	ucfg_qmi_wfds_register_os_if_callbacks(qmi_ctx, cb_obj);
 }

+ 105 - 0
components/qmi/dispatcher/src/wlan_qmi_wfds_api.c

@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_qmi_wfds_api.c
+ *
+ * QMI component north bound interface definitions
+ */
+
+#include "wlan_qmi_wfds_api.h"
+#include "wlan_qmi_objmgr.h"
+#include "wlan_qmi_priv.h"
+#include "wlan_qmi_main.h"
+
+QDF_STATUS wlan_qmi_wfds_init(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_qmi_psoc_context *qmi_ctx = qmi_psoc_get_priv(psoc);
+
+	if (!qmi_ctx) {
+		qmi_err("QMI context is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (qmi_ctx->qmi_cbs.qmi_wfds_init)
+		return qmi_ctx->qmi_cbs.qmi_wfds_init();
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+void wlan_qmi_wfds_deinit(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_qmi_psoc_context *qmi_ctx = qmi_psoc_get_priv(psoc);
+
+	if (!qmi_ctx) {
+		qmi_err("QMI context is NULL");
+		return;
+	}
+
+	if (qmi_ctx->qmi_cbs.qmi_wfds_deinit)
+		qmi_ctx->qmi_cbs.qmi_wfds_deinit();
+}
+
+QDF_STATUS
+wlan_qmi_wfds_send_config_msg(struct wlan_objmgr_psoc *psoc,
+			      struct wlan_qmi_wfds_config_req_msg *src_info)
+{
+	struct wlan_qmi_psoc_context *qmi_ctx = qmi_psoc_get_priv(psoc);
+
+	if (!qmi_ctx) {
+		qmi_err("QMI context is NULL");
+		return  QDF_STATUS_E_INVAL;
+	}
+
+	if (qmi_ctx->qmi_cbs.qmi_wfds_send_config_msg)
+		return qmi_ctx->qmi_cbs.qmi_wfds_send_config_msg(src_info);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wlan_qmi_wfds_send_req_mem_msg(struct wlan_objmgr_psoc *psoc,
+			       struct wlan_qmi_wfds_mem_req_msg *src_info)
+{
+	struct wlan_qmi_psoc_context *qmi_ctx = qmi_psoc_get_priv(psoc);
+
+	if (!qmi_ctx) {
+		qmi_err("QMI context is NULL");
+		return  QDF_STATUS_E_INVAL;
+	}
+
+	if (qmi_ctx->qmi_cbs.qmi_wfds_send_req_mem_msg)
+		return qmi_ctx->qmi_cbs.qmi_wfds_send_req_mem_msg(src_info);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wlan_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_objmgr_psoc *psoc,
+			struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info)
+{
+	struct wlan_qmi_psoc_context *qmi_ctx = qmi_psoc_get_priv(psoc);
+
+	if (!qmi_ctx) {
+		qmi_err("QMI context is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (qmi_ctx->qmi_cbs.qmi_wfds_send_ipcc_map_n_cfg_msg)
+		return qmi_ctx->qmi_cbs.qmi_wfds_send_ipcc_map_n_cfg_msg(src_info);
+
+	return QDF_STATUS_E_FAILURE;
+}

+ 23 - 0
os_if/qmi/inc/os_if_qmi.h

@@ -30,6 +30,14 @@
 #include <linux/types.h>
 #include "wlan_cfg80211.h"
 #include "wlan_objmgr_psoc_obj.h"
+#include <qdf_time.h>
+
+#define QMI_WFDS_MAX_RECV_BUF_SIZE  4096
+#define QMI_WFDS_SERVICE_INS_ID_V01 0x0
+#define QMI_WFDS_TIMEOUT_MS         10000
+#define QMI_WFDS_TIMEOUT_JF         \
+	qdf_system_msecs_to_ticks(QMI_WFDS_TIMEOUT_MS)
+
 
 #ifdef QMI_COMPONENT_ENABLE
 /**
@@ -134,6 +142,21 @@ void os_if_qmi_txn_cancel(struct qmi_txn *qmi_txn);
  */
 void os_if_qmi_register_callbacks(struct wlan_objmgr_psoc *psoc,
 				  struct wlan_qmi_psoc_callbacks *cb_obj);
+
+#ifdef QMI_WFDS
+/**
+ * os_if_qmi_wfds_register_callbacks() - Register WFDS callback handlers
+ * @cb_obj: Callback object pointer
+ *
+ * Return: None
+ */
+void os_if_qmi_wfds_register_callbacks(struct wlan_qmi_psoc_callbacks *cb_obj);
+#else
+static inline
+void os_if_qmi_wfds_register_callbacks(struct wlan_qmi_psoc_callbacks *cb_obj)
+{
+}
+#endif
 #else
 static inline
 QDF_STATUS os_if_qmi_handle_init(struct qmi_handle *qmi_hdl,

+ 292 - 0
os_if/qmi/inc/os_if_qmi_wifi_driver_service_v01.h

@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef WIFI_DRIVER_SERVICE_V01_H
+#define WIFI_DRIVER_SERVICE_V01_H
+
+#include <linux/soc/qcom/qmi.h>
+
+#define WFDS_SERVICE_ID_V01 0x043C
+#define WFDS_SERVICE_VERS_V01 0x01
+
+#define QMI_WFDS_IPCC_MAP_N_CFG_RESP_V01 0x0003
+#define QMI_WFDS_MISC_REQ_V01 0x0004
+#define QMI_WFDS_MISC_RESP_V01 0x0004
+#define QMI_WFDS_MEM_RESP_V01 0x0002
+#define QMI_WFDS_IPCC_MAP_N_CFG_REQ_V01 0x0003
+#define QMI_WFDS_MISC_IND_V01 0x0004
+#define QMI_WFDS_CONFIG_REQ_V01 0x0001
+#define QMI_WFDS_IPCC_MAP_N_CFG_IND_V01 0x0003
+#define QMI_WFDS_CONFIG_RESP_V01 0x0001
+#define QMI_WFDS_MEM_REQ_V01 0x0002
+#define QMI_WFDS_MEM_IND_V01 0x0002
+
+#define WFDS_CE_MAX_SRNG_V01 3
+#define WFDS_MEM_ARENA_MAX_V01 8
+#define WFDS_PAGE_INFO_MAX_ARRAY_SIZE_V01 255
+
+/**
+ * struct wfds_gen_resp_msg_v01 - Generic QMI response message
+ * @resp: QMI result code
+ */
+struct wfds_gen_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+
+#define WFDS_GEN_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wfds_gen_resp_msg_v01_ei[];
+
+/**
+ * enum wifi_drv_qmi_srng_direction_v01 - SRNG direction
+ * @WIFI_DRV_QMI_SRNG_DIRECTION_MIN_VAL_V01: SRNG direction enum min value
+ * @WFDS_SRNG_SOURCE_RING_V01: SRNG source ring
+ * @WFDS_SRNG_DESTINATION_RING_V01: SRNG destination ring
+ * @WIFI_DRV_QMI_SRNG_DIRECTION_MAX_VAL_V01: SRNG direction enum max value
+ */
+enum wifi_drv_qmi_srng_direction_v01 {
+	WIFI_DRV_QMI_SRNG_DIRECTION_MIN_VAL_V01 = INT_MIN,
+	WFDS_SRNG_SOURCE_RING_V01 = 0,
+	WFDS_SRNG_DESTINATION_RING_V01 = 1,
+	WIFI_DRV_QMI_SRNG_DIRECTION_MAX_VAL_V01 = INT_MAX,
+};
+
+/**
+ * struct wifi_drv_qmi_srng_information_v01 - SRNG information
+ * @ring_id: SRNG ring id
+ * @dir: SRNG direction
+ * @num_entries: number of entries in SRNG
+ * @entry_size: size of SRNG descriptor
+ * @ring_base_paddr: ring base physical address of SRNG
+ * @hp_paddr: HP physical address of SRNG
+ * @tp_paddr: TP physical address of SRNG
+ */
+struct wifi_drv_qmi_srng_information_v01 {
+	u8 ring_id;
+	enum wifi_drv_qmi_srng_direction_v01 dir;
+	u32 num_entries;
+	u32 entry_size;
+	u64 ring_base_paddr;
+	u64 hp_paddr;
+	u64 tp_paddr;
+};
+
+/**
+ * enum wifi_drv_qmi_pipe_dir_v01 - pipe direction
+ * @WIFI_DRV_QMI_PIPE_DIR_MIN_VAL_V01: pipe direction enum min value
+ * @WFDS_PIPEDIR_NONE_V01: none pipe direction
+ * @WFDS_PIPEDIR_IN_V01: target to host pipe direction
+ * @WFDS_PIPEDIR_OUT_V01:  host to target pipe direction
+ * @WIFI_DRV_QMI_PIPE_DIR_MAX_VAL_V01: pipe direction enum max value
+ */
+enum wifi_drv_qmi_pipe_dir_v01 {
+	WIFI_DRV_QMI_PIPE_DIR_MIN_VAL_V01 = INT_MIN,
+	WFDS_PIPEDIR_NONE_V01 = 0,
+	WFDS_PIPEDIR_IN_V01 = 1,
+	WFDS_PIPEDIR_OUT_V01 = 2,
+	WIFI_DRV_QMI_PIPE_DIR_MAX_VAL_V01 = INT_MAX,
+};
+
+/**
+ * struct wifi_drv_qmi_ce_information_v01 - CE information
+ * @ce_id: CE id
+ * @ce_dir: CE direction
+ * @srng_info: SRNG information
+ */
+struct wifi_drv_qmi_ce_information_v01 {
+	u8 ce_id;
+	enum wifi_drv_qmi_pipe_dir_v01 ce_dir;
+	struct wifi_drv_qmi_srng_information_v01 srng_info;
+};
+
+/**
+ * struct wfds_config_req_msg_v01 - WFDS config request message
+ * @ce_info_len: size of ce_info with valid entries
+ * @ce_info: CE information array
+ * @rx_refill_ring: refill SRNG information
+ * @shadow_rdptr_mem_paddr: shadow read memory physical address
+ * @shadow_rdptr_mem_size:  shadow read memory size
+ * @shadow_wrptr_mem_paddr: shadow write memory physical address
+ * @shadow_wrptr_mem_size: shadow write memory size
+ * @rx_pkt_tlv_len: rx packet tlvs length
+ * @rx_rbm: return buffer manager for rx buffers
+ * @pcie_bar_pa: PCIe BAR physical address
+ * @pci_slot: PCIe slot
+ * @lpass_ep_id: LPASS data message service endpoint id
+ */
+struct wfds_config_req_msg_v01 {
+	u32 ce_info_len;
+	struct wifi_drv_qmi_ce_information_v01 ce_info[WFDS_CE_MAX_SRNG_V01];
+	struct wifi_drv_qmi_srng_information_v01 rx_refill_ring;
+	u64 shadow_rdptr_mem_paddr;
+	u64 shadow_rdptr_mem_size;
+	u64 shadow_wrptr_mem_paddr;
+	u64 shadow_wrptr_mem_size;
+	u32 rx_pkt_tlv_len;
+	u32 rx_rbm;
+	u64 pcie_bar_pa;
+	u32 pci_slot;
+	u32 lpass_ep_id;
+};
+
+#define WFDS_CONFIG_REQ_MSG_V01_MAX_MSG_LEN 253
+extern struct qmi_elem_info wfds_config_req_msg_v01_ei[];
+
+/**
+ * enum wifi_drv_qmi_mem_arenas_v01 - Memory arena
+ * @WIFI_DRV_QMI_MEM_ARENAS_MIN_VAL_V01: memory arena enum min value
+ * @WFDS_MEM_ARENA_TX_BUFFERS_V01: TX buffers memory arena
+ * @WFDS_MEM_ARENA_CE_TX_MSG_BUFFERS_V01: CE TX message buffers memory arena
+ * @WFDS_MEM_ARENA_CE_RX_MSG_BUFFERS_V01: CE RX message buffers memory arena
+ * @WIFI_DRV_QMI_MEM_ARENAS_MAX_VAL_V01: memory arena enum max value
+ */
+enum wifi_drv_qmi_mem_arenas_v01 {
+	WIFI_DRV_QMI_MEM_ARENAS_MIN_VAL_V01 = INT_MIN,
+	WFDS_MEM_ARENA_TX_BUFFERS_V01 = 0,
+	WFDS_MEM_ARENA_CE_TX_MSG_BUFFERS_V01 = 1,
+	WFDS_MEM_ARENA_CE_RX_MSG_BUFFERS_V01 = 2,
+	WIFI_DRV_QMI_MEM_ARENAS_MAX_VAL_V01 = INT_MAX,
+};
+
+/**
+ * struct wifi_drv_qmi_mem_arena_information_v01 - Memory arena information
+ * @entry_size: entry size
+ * @num_entries: total number of entries required
+ */
+struct wifi_drv_qmi_mem_arena_information_v01 {
+	u16 entry_size;
+	u16 num_entries;
+};
+
+/**
+ * struct wfds_mem_ind_msg_v01 - Memory indication message
+ * @mem_arena_info_len: number of valid entries in mem_arena_info array
+ * @mem_arena_info: memory arena information array
+ */
+struct wfds_mem_ind_msg_v01 {
+	u32 mem_arena_info_len;
+	struct wifi_drv_qmi_mem_arena_information_v01 mem_arena_info[WFDS_MEM_ARENA_MAX_V01];
+};
+
+#define WFDS_MEM_IND_MSG_V01_MAX_MSG_LEN 36
+extern struct qmi_elem_info wfds_mem_ind_msg_v01_ei[];
+
+/**
+ * struct wifi_drv_qmi_mem_arena_page_information_v01 - Memory arena
+ *  page information
+ * @num_entries_per_page: number of entries per page
+ * @page_dma_addr_len: number of valid entries in page_dma_addr array
+ * @page_dma_addr: page dma address array
+ */
+struct wifi_drv_qmi_mem_arena_page_information_v01 {
+	u16 num_entries_per_page;
+	u32 page_dma_addr_len;
+	u64 page_dma_addr[WFDS_PAGE_INFO_MAX_ARRAY_SIZE_V01];
+};
+
+/**
+ * struct wfds_mem_req_msg_v01 - Memory request message
+ *  page information
+ * @mem_arena_page_info_len: number of valid entries in
+ *  mem_arena_page_info array
+ * @mem_arena_page_info: memory arena information
+ */
+struct wfds_mem_req_msg_v01 {
+	u32 mem_arena_page_info_len;
+	struct wifi_drv_qmi_mem_arena_page_information_v01 mem_arena_page_info[WFDS_MEM_ARENA_MAX_V01];
+};
+
+#define WFDS_MEM_REQ_MSG_V01_MAX_MSG_LEN 16348
+extern struct qmi_elem_info wfds_mem_req_msg_v01_ei[];
+
+/**
+ * struct wifi_drv_qmi_ipcc_information_v01 - IPCC information
+ * @ce_id: CE id
+ * @ipcc_trig_addr: IPCC trigger address
+ * @ipcc_trig_data: IPCC trigger data
+ */
+struct wifi_drv_qmi_ipcc_information_v01 {
+	u8 ce_id;
+	u64 ipcc_trig_addr;
+	u32 ipcc_trig_data;
+};
+
+/**
+ * struct wfds_ipcc_map_n_cfg_ind_msg_v01 - IPCC map and configure
+ *  indication message
+ * @ipcc_ce_info_len: number of valid entries in ipcc_ce_info array
+ * @ipcc_ce_info: IPCC information for CE
+ */
+struct wfds_ipcc_map_n_cfg_ind_msg_v01 {
+	u32 ipcc_ce_info_len;
+	struct wifi_drv_qmi_ipcc_information_v01 ipcc_ce_info[WFDS_CE_MAX_SRNG_V01];
+};
+
+#define WFDS_IPCC_MAP_N_CFG_IND_MSG_V01_MAX_MSG_LEN 43
+extern struct qmi_elem_info wfds_ipcc_map_n_cfg_ind_msg_v01_ei[];
+
+/**
+ * struct wfds_ipcc_map_n_cfg_req_msg_v01 - IPCC map and configure
+ *  request message
+ * @status: IPCC configuration status
+ */
+struct wfds_ipcc_map_n_cfg_req_msg_v01 {
+	u8 status;
+};
+
+#define WFDS_IPCC_MAP_N_CFG_REQ_MSG_V01_MAX_MSG_LEN 4
+extern struct qmi_elem_info wfds_ipcc_map_n_cfg_req_msg_v01_ei[];
+
+/**
+ * enum wifi_drv_qmi_event_v01 - driver event
+ * @WIFI_DRV_QMI_EVENT_MIN_VAL_V01: event enum min value
+ * @WFDS_EVENT_WLAN_HOST_RMMOD_V01: host driver rmmod event
+ * @WFDS_EVENT_WLAN_SSR_V01: wlan SSR event
+ * @WFDS_EVENT_LPASS_SSR_V01: LPASS SSR event
+ * @WIFI_DRV_QMI_EVENT_MAX_VAL_V01: event enum max value
+ */
+enum wifi_drv_qmi_event_v01 {
+	WIFI_DRV_QMI_EVENT_MIN_VAL_V01 = INT_MIN,
+	WFDS_EVENT_WLAN_HOST_RMMOD_V01 = 0,
+	WFDS_EVENT_WLAN_SSR_V01 = 1,
+	WFDS_EVENT_LPASS_SSR_V01 = 2,
+	WIFI_DRV_QMI_EVENT_MAX_VAL_V01 = INT_MAX,
+};
+
+/**
+ * struct wfds_misc_req_msg_v01 - Miscellaneous request
+ *  message
+ * @event: driver event
+ */
+struct wfds_misc_req_msg_v01 {
+	enum wifi_drv_qmi_event_v01 event;
+};
+
+#define WFDS_MISC_REQ_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wfds_misc_req_msg_v01_ei[];
+
+/**
+ * struct wfds_misc_ind_msg_v01 - Miscellaneous indication
+ *  message
+ * @event: driver event
+ */
+struct wfds_misc_ind_msg_v01 {
+	enum wifi_drv_qmi_event_v01 event;
+};
+
+#define WFDS_MISC_IND_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wfds_misc_ind_msg_v01_ei[];
+
+#endif

+ 3 - 0
os_if/qmi/src/os_if_qmi.c

@@ -21,6 +21,7 @@
  */
 
 #include "os_if_qmi.h"
+#include "wlan_qmi_ucfg_api.h"
 
 QDF_STATUS os_if_qmi_handle_init(struct qmi_handle *qmi_hdl,
 				 qdf_size_t recv_buf_size,
@@ -130,4 +131,6 @@ void os_if_qmi_txn_cancel(struct qmi_txn *qmi_txn)
 void os_if_qmi_register_callbacks(struct wlan_objmgr_psoc *psoc,
 				  struct wlan_qmi_psoc_callbacks *cb_obj)
 {
+	os_if_qmi_wfds_register_callbacks(cb_obj);
+	ucfg_qmi_register_os_if_callbacks(psoc, cb_obj);
 }

+ 513 - 0
os_if/qmi/src/os_if_qmi_wfds.c

@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "os_if_qmi.h"
+#include "os_if_qmi_wifi_driver_service_v01.h"
+#include <qdf_util.h>
+#include "wlan_qmi_public_struct.h"
+
+static struct qmi_handle qmi_wfds;
+
+/*
+ * os_if_ce_dir_qmi_to_wfds_type() - Convert ce direction from internal
+ *  type to type used in QMI message
+ * @ce_dir: internal ce direction
+ *
+ * Return: ce direction in QMI type
+ */
+static enum wifi_drv_qmi_pipe_dir_v01
+os_if_ce_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_pipe_dir ce_dir)
+{
+	switch (ce_dir) {
+	case QMI_WFDS_PIPEDIR_NONE:
+		return WFDS_PIPEDIR_NONE_V01;
+	case QMI_WFDS_PIPEDIR_IN:
+		return WFDS_PIPEDIR_IN_V01;
+	case QMI_WFDS_PIPEDIR_OUT:
+		return WFDS_PIPEDIR_OUT_V01;
+	default:
+		return WIFI_DRV_QMI_PIPE_DIR_MAX_VAL_V01;
+	}
+}
+
+/*
+ * os_if_srng_dir_qmi_to_wfds_type() - Convert srng direction from internal
+ *  type to type used in QMI message
+ * @srng_dir: internal srng direction
+ *
+ * Return: srng direction in QMI type
+ */
+static enum wifi_drv_qmi_srng_direction_v01
+os_if_srng_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_srng_dir srng_dir)
+{
+	switch (srng_dir) {
+	case QMI_WFDS_SRNG_SOURCE_RING:
+		return WFDS_SRNG_SOURCE_RING_V01;
+	case QMI_WFDS_SRNG_DESTINATION_RING:
+		return WFDS_SRNG_DESTINATION_RING_V01;
+	default:
+		return WIFI_DRV_QMI_SRNG_DIRECTION_MAX_VAL_V01;
+	}
+}
+
+/*
+ * os_if_qmi_wfds_send_config_msg() - Send config message to QMI server
+ *  to QMI server
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS
+os_if_qmi_wfds_send_config_msg(struct wlan_qmi_wfds_config_req_msg *src_info)
+{
+	struct wfds_config_req_msg_v01 *req;
+	struct wfds_gen_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	QDF_STATUS status;
+	uint8_t i;
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req)
+		return QDF_STATUS_E_NOMEM;
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp) {
+		qdf_mem_free(req);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	if (src_info->ce_info_len > QMI_WFDS_CE_MAX_SRNG) {
+		status = QDF_STATUS_E_INVAL;
+		goto out;
+	}
+
+	req->ce_info_len = src_info->ce_info_len;
+	for (i = 0; i < req->ce_info_len; i++) {
+		req->ce_info[i].ce_id = src_info->ce_info[i].ce_id;
+		req->ce_info[i].ce_dir =
+		     os_if_ce_dir_qmi_to_wfds_type(src_info->ce_info[i].ce_dir);
+		req->ce_info[i].srng_info.ring_id =
+			src_info->ce_info[i].srng_info.ring_id;
+		req->ce_info[i].srng_info.dir =
+			os_if_srng_dir_qmi_to_wfds_type(src_info->ce_info[i].srng_info.dir);
+		req->ce_info[i].srng_info.num_entries =
+			src_info->ce_info[i].srng_info.num_entries;
+		req->ce_info[i].srng_info.entry_size =
+			src_info->ce_info[i].srng_info.entry_size;
+		req->ce_info[i].srng_info.ring_base_paddr =
+			src_info->ce_info[i].srng_info.ring_base_paddr;
+		req->ce_info[i].srng_info.hp_paddr =
+			src_info->ce_info[i].srng_info.hp_paddr;
+		req->ce_info[i].srng_info.tp_paddr =
+			src_info->ce_info[i].srng_info.tp_paddr;
+	}
+
+	req->rx_refill_ring.ring_id = src_info->rx_refill_ring.ring_id;
+	req->rx_refill_ring.dir =
+		os_if_srng_dir_qmi_to_wfds_type(src_info->rx_refill_ring.dir);
+	req->rx_refill_ring.num_entries = src_info->rx_refill_ring.num_entries;
+	req->rx_refill_ring.entry_size = src_info->rx_refill_ring.entry_size;
+	req->rx_refill_ring.ring_base_paddr =
+				src_info->rx_refill_ring.ring_base_paddr;
+	req->rx_refill_ring.hp_paddr = src_info->rx_refill_ring.hp_paddr;
+	req->rx_refill_ring.tp_paddr = src_info->rx_refill_ring.tp_paddr;
+
+	req->shadow_rdptr_mem_paddr = src_info->shadow_rdptr_mem_paddr;
+	req->shadow_rdptr_mem_size = src_info->shadow_rdptr_mem_size;
+	req->shadow_wrptr_mem_paddr = src_info->shadow_wrptr_mem_paddr;
+	req->shadow_wrptr_mem_size = src_info->shadow_wrptr_mem_size;
+	req->rx_pkt_tlv_len = src_info->rx_pkt_tlv_len;
+	req->rx_rbm = src_info->rx_rbm;
+	req->pcie_bar_pa = src_info->pcie_bar_pa;
+	req->pci_slot = src_info->pci_slot;
+	req->lpass_ep_id = src_info->lpass_ep_id;
+
+	status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
+				    resp);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI transaction init failed for WFDS config message");
+		goto out;
+	}
+
+	status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
+					QMI_WFDS_CONFIG_REQ_V01,
+					WFDS_CONFIG_REQ_MSG_V01_MAX_MSG_LEN,
+					wfds_config_req_msg_v01_ei, req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI WFDS config send request failed");
+		os_if_qmi_txn_cancel(&txn);
+		goto out;
+	}
+
+	status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("Failed to wait for QMI WFDS config response");
+		goto out;
+	}
+
+	qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
+
+out:
+	qdf_mem_free(resp);
+	qdf_mem_free(req);
+
+	return status;
+}
+
+/*
+ * os_if_qmi_wfds_send_req_mem_msg() - Send Request Memory message to QMI server
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS
+os_if_qmi_wfds_send_req_mem_msg(struct wlan_qmi_wfds_mem_req_msg *src_info)
+{
+	struct wfds_mem_req_msg_v01 *req;
+	struct wfds_gen_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	QDF_STATUS status;
+	uint8_t i;
+	uint16_t j;
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req)
+		return QDF_STATUS_E_NOMEM;
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp) {
+		qdf_mem_free(req);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	if (src_info->mem_arena_page_info_len > QMI_WFDS_MEM_ARENA_MAX) {
+		status = QDF_STATUS_E_INVAL;
+		goto out;
+	}
+
+	req->mem_arena_page_info_len = src_info->mem_arena_page_info_len;
+	for (i = 0; i < req->mem_arena_page_info_len; i++) {
+		req->mem_arena_page_info[i].num_entries_per_page =
+			src_info->mem_arena_page_info[i].num_entries_per_page;
+		req->mem_arena_page_info[i].page_dma_addr_len =
+			src_info->mem_arena_page_info[i].page_dma_addr_len;
+
+		if (src_info->mem_arena_page_info[i].page_dma_addr_len >
+		    QMI_WFDS_PAGE_INFO_ARRAY_MAX_SIZE) {
+			status = QDF_STATUS_E_INVAL;
+			goto out;
+		}
+
+		for (j = 0; j < req->mem_arena_page_info[i].page_dma_addr_len;
+		     j++)
+			req->mem_arena_page_info[i].page_dma_addr[j] =
+			      src_info->mem_arena_page_info[i].page_dma_addr[j];
+	}
+
+	status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
+				    resp);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI transaction init failed for WFDS config message");
+		goto out;
+	}
+
+	status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
+					QMI_WFDS_MEM_REQ_V01,
+					WFDS_MEM_REQ_MSG_V01_MAX_MSG_LEN,
+					wfds_mem_req_msg_v01_ei, req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI WFDS config send request failed");
+		os_if_qmi_txn_cancel(&txn);
+		goto out;
+	}
+
+	status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("Failed to wait for QMI WFDS config response");
+		goto out;
+	}
+
+	qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
+
+out:
+	qdf_mem_free(resp);
+	qdf_mem_free(req);
+
+	return status;
+}
+
+/*
+ * os_if_srng_dir_qmi_to_wfds_type() - Convert status from internal
+ *  type to type used in QMI message
+ * @status: internal status
+ *
+ * Return: status in QMI type
+ */
+static uint8_t
+os_if_status_qmi_to_wfds_type(enum wlan_qmi_wfds_status status)
+{
+	switch (status) {
+	case QMI_WFDS_STATUS_SUCCESS:
+		return QMI_RESULT_SUCCESS_V01;
+	case QMI_WFDS_STATUS_FAILURE:
+	default:
+		return QMI_RESULT_FAILURE_V01;
+	}
+}
+
+/*
+ * os_if_qmi_wfds_ipcc_map_n_cfg_msg() - Send the IPCC map and configure message
+ *  to QMI server
+ * @src_info: source information to be filled in QMI message
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS
+os_if_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info)
+{
+	struct wfds_ipcc_map_n_cfg_req_msg_v01 *req;
+	struct wfds_gen_resp_msg_v01 *resp;
+	struct qmi_txn txn;
+	QDF_STATUS status;
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req)
+		return QDF_STATUS_E_NOMEM;
+
+	resp = qdf_mem_malloc(sizeof(*resp));
+	if (!resp) {
+		qdf_mem_free(req);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	req->status = os_if_status_qmi_to_wfds_type(src_info->status);
+
+	status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
+				    resp);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI transaction init failed for WFDS config message");
+		goto out;
+	}
+
+	status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
+				    QMI_WFDS_IPCC_MAP_N_CFG_REQ_V01,
+				    WFDS_IPCC_MAP_N_CFG_REQ_MSG_V01_MAX_MSG_LEN,
+				    wfds_ipcc_map_n_cfg_req_msg_v01_ei, req);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("QMI WFDS config send request failed");
+		os_if_qmi_txn_cancel(&txn);
+		goto out;
+	}
+
+	status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_info("Failed to wait for QMI WFDS config response");
+		goto out;
+	}
+
+	qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
+
+out:
+	qdf_mem_free(resp);
+	qdf_mem_free(req);
+
+	return status;
+}
+
+/*
+ * os_if_qmi_wfds_request_mem_ind_cb() - Process request memory indication
+ *  received from QMI server
+ * @qmi_hdl: QMI handle
+ * @sq: pointer to QRTR sock address
+ * @qmi_txn: pointer to QMI transaction
+ * @data: pointer to QMI data
+ *
+ * Return: None
+ */
+static void os_if_qmi_wfds_request_mem_ind_cb(struct qmi_handle *qmi_hdl,
+					      struct sockaddr_qrtr *sq,
+					      struct qmi_txn *qmi_txn,
+					      const void *data)
+{
+	struct wfds_mem_ind_msg_v01 *src_info =
+				(struct wfds_mem_ind_msg_v01 *)data;
+	struct wlan_qmi_wfds_mem_ind_msg mem_ind_msg = {0};
+	uint8_t i;
+
+	if (!qmi_hdl || !qmi_txn)
+		return;
+
+	if (src_info->mem_arena_info_len > QMI_WFDS_MEM_ARENA_MAX) {
+		osif_info("Memory arena information array size %d exceeds max length",
+			  src_info->mem_arena_info_len);
+		return;
+	}
+
+	mem_ind_msg.mem_arena_info_len = src_info->mem_arena_info_len;
+	for (i = 0; i < src_info->mem_arena_info_len; i++) {
+		mem_ind_msg.mem_arena_info[i].entry_size =
+				src_info->mem_arena_info[i].entry_size;
+		mem_ind_msg.mem_arena_info[i].num_entries =
+				src_info->mem_arena_info[i].num_entries;
+	}
+}
+
+/*
+ * os_if_wfds_ipcc_map_n_cfg_ind_cb() - Process IPCC map and configure
+ *  indication received from QMI server
+ * @qmi_hdl: QMI handle
+ * @sq: pointer to QRTR sock address
+ * @qmi_txn: pointer to QMI transaction
+ * @data: pointer to QMI data
+ *
+ * Return: None
+ */
+static void os_if_wfds_ipcc_map_n_cfg_ind_cb(struct qmi_handle *qmi_hdl,
+					     struct sockaddr_qrtr *sq,
+					     struct qmi_txn *qmi_txn,
+					     const void *data)
+{
+	struct wfds_ipcc_map_n_cfg_ind_msg_v01 *src_info =
+		(struct wfds_ipcc_map_n_cfg_ind_msg_v01 *)data;
+	struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg ipcc_ind_msg = {0};
+	uint8_t i;
+
+	if (!qmi_hdl || !qmi_txn)
+		return;
+
+	if (src_info->ipcc_ce_info_len > QMI_WFDS_CE_MAX_SRNG) {
+		osif_info("IPCC CE information array size %d exceeds max length",
+			  src_info->ipcc_ce_info_len);
+		return;
+	}
+
+	ipcc_ind_msg.ipcc_ce_info_len = src_info->ipcc_ce_info_len;
+	for (i = 0; i < src_info->ipcc_ce_info_len; i++) {
+		ipcc_ind_msg.ipcc_ce_info[i].ce_id =
+				src_info->ipcc_ce_info[i].ce_id;
+		ipcc_ind_msg.ipcc_ce_info[i].ipcc_trig_addr =
+				src_info->ipcc_ce_info[i].ipcc_trig_addr;
+		ipcc_ind_msg.ipcc_ce_info[i].ipcc_trig_data =
+				src_info->ipcc_ce_info[i].ipcc_trig_data;
+	}
+}
+
+/**
+ * os_if_qmi_wfds_new_server() - New server callback triggered when service is
+ *  up.
+ * @qmi_hdl: QMI client handle
+ * @qmi_svc: QMI service handle
+ *
+ * Returns: 0 on success else OS failure code
+ */
+static int
+os_if_qmi_wfds_new_server(struct qmi_handle *qmi_hdl,
+			  struct qmi_service *qmi_svc)
+{
+	QDF_STATUS status;
+
+	status = os_if_qmi_connect_to_svc(qmi_hdl, qmi_svc);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("Failed to connect to WFDS QMI service port");
+		return qdf_status_to_os_return(status);
+	}
+
+	return qdf_status_to_os_return(status);
+}
+
+/**
+ * os_if_qmi_wfds_del_server() - Del server callback triggered when service is
+ *  down.
+ * @qmi_hdl: QMI client handle
+ * @qmi_svc: QMI service handle
+ *
+ * Returns: None
+ */
+static void
+os_if_qmi_wfds_del_server(struct qmi_handle *qmi_hdl,
+			  struct qmi_service *qmi_svc)
+{
+}
+
+static struct qmi_msg_handler qmi_wfds_msg_handler[] = {
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WFDS_MEM_REQ_V01,
+		.ei = wfds_mem_ind_msg_v01_ei,
+		.decoded_size = sizeof(struct wfds_mem_ind_msg_v01),
+		.fn = os_if_qmi_wfds_request_mem_ind_cb
+	},
+	{
+		.type = QMI_INDICATION,
+		.msg_id = QMI_WFDS_IPCC_MAP_N_CFG_IND_V01,
+		.ei = wfds_ipcc_map_n_cfg_ind_msg_v01_ei,
+		.decoded_size = sizeof(struct wfds_ipcc_map_n_cfg_ind_msg_v01),
+		.fn = os_if_wfds_ipcc_map_n_cfg_ind_cb
+	},
+};
+
+static struct qmi_ops qmi_wfds_ops = {
+	.new_server = os_if_qmi_wfds_new_server,
+	.del_server = os_if_qmi_wfds_del_server,
+};
+
+/**
+ * os_if_qmi_wfds_init() - Initialize WFDS QMI client
+ *
+ * Returns: QDF status
+ */
+static QDF_STATUS os_if_qmi_wfds_init(void)
+{
+	QDF_STATUS status;
+
+	status = os_if_qmi_handle_init(&qmi_wfds, QMI_WFDS_MAX_RECV_BUF_SIZE,
+				       &qmi_wfds_ops, qmi_wfds_msg_handler);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("WFDS QMI handle init failed");
+		return status;
+	}
+
+	status = os_if_qmi_add_lookup(&qmi_wfds, WFDS_SERVICE_ID_V01,
+				      WFDS_SERVICE_VERS_V01,
+				      QMI_WFDS_SERVICE_INS_ID_V01);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("WFDS QMI add lookup failed");
+		os_if_qmi_handle_release(&qmi_wfds);
+		return status;
+	}
+
+	return status;
+}
+
+/**
+ * os_if_qmi_wfds_deinit() - Deinitialize WFDS QMI client
+ *
+ * Returns: None
+ */
+static void os_if_qmi_wfds_deinit(void)
+{
+	os_if_qmi_handle_release(&qmi_wfds);
+}
+
+void os_if_qmi_wfds_register_callbacks(struct wlan_qmi_psoc_callbacks *cb_obj)
+{
+	cb_obj->qmi_wfds_init = os_if_qmi_wfds_init;
+	cb_obj->qmi_wfds_deinit = os_if_qmi_wfds_deinit;
+	cb_obj->qmi_wfds_send_config_msg = os_if_qmi_wfds_send_config_msg;
+	cb_obj->qmi_wfds_send_req_mem_msg = os_if_qmi_wfds_send_req_mem_msg;
+	cb_obj->qmi_wfds_send_ipcc_map_n_cfg_msg =
+					os_if_qmi_wfds_ipcc_map_n_cfg_msg;
+}

+ 489 - 0
os_if/qmi/src/os_if_qmi_wifi_driver_service_v01.c

@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "os_if_qmi_wifi_driver_service_v01.h"
+#include <linux/module.h>
+
+struct qmi_elem_info wfds_gen_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct wfds_gen_resp_msg_v01,
+					   resp),
+		.ei_array       = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info wifi_drv_qmi_srng_information_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   ring_id),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wifi_drv_qmi_srng_direction_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   dir),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   num_entries),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   entry_size),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   ring_base_paddr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   hp_paddr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_srng_information_v01,
+					   tp_paddr),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info wifi_drv_qmi_ce_information_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ce_information_v01,
+					   ce_id),
+	},
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wifi_drv_qmi_pipe_dir_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ce_information_v01,
+					   ce_dir),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct wifi_drv_qmi_srng_information_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ce_information_v01,
+					   srng_info),
+		.ei_array       = wifi_drv_qmi_srng_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_config_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   ce_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = WFDS_CE_MAX_SRNG_V01,
+		.elem_size      = sizeof(struct wifi_drv_qmi_ce_information_v01),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   ce_info),
+		.ei_array       = wifi_drv_qmi_ce_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct wifi_drv_qmi_srng_information_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   rx_refill_ring),
+		.ei_array       = wifi_drv_qmi_srng_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x03,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   shadow_rdptr_mem_paddr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x04,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   shadow_rdptr_mem_size),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x05,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   shadow_wrptr_mem_paddr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x06,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   shadow_wrptr_mem_size),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x07,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   rx_pkt_tlv_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x08,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   rx_rbm),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x09,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   pcie_bar_pa),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x0A,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   pci_slot),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x0B,
+		.offset         = offsetof(struct wfds_config_req_msg_v01,
+					   lpass_ep_id),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info wifi_drv_qmi_mem_arena_information_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_2_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_mem_arena_information_v01,
+					   entry_size),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_2_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_mem_arena_information_v01,
+					   num_entries),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_mem_ind_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_mem_ind_msg_v01,
+					   mem_arena_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = WFDS_MEM_ARENA_MAX_V01,
+		.elem_size      = sizeof(struct wifi_drv_qmi_mem_arena_information_v01),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_mem_ind_msg_v01,
+					   mem_arena_info),
+		.ei_array       = wifi_drv_qmi_mem_arena_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info wifi_drv_qmi_mem_arena_page_information_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_2_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u16),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_mem_arena_page_information_v01,
+					   num_entries_per_page),
+	},
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_mem_arena_page_information_v01,
+					   page_dma_addr_len),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = WFDS_PAGE_INFO_MAX_ARRAY_SIZE_V01,
+		.elem_size      = sizeof(u64),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_mem_arena_page_information_v01,
+					   page_dma_addr),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_mem_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_mem_req_msg_v01,
+					   mem_arena_page_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = WFDS_MEM_ARENA_MAX_V01,
+		.elem_size      = sizeof(struct wifi_drv_qmi_mem_arena_page_information_v01),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_mem_req_msg_v01,
+					   mem_arena_page_info),
+		.ei_array       = wifi_drv_qmi_mem_arena_page_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info wifi_drv_qmi_ipcc_information_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ipcc_information_v01,
+					   ce_id),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ipcc_information_v01,
+					   ipcc_trig_addr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0,
+		.offset         = offsetof(struct wifi_drv_qmi_ipcc_information_v01,
+					   ipcc_trig_data),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_ipcc_map_n_cfg_ind_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_DATA_LEN,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_ipcc_map_n_cfg_ind_msg_v01,
+					   ipcc_ce_info_len),
+	},
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = WFDS_CE_MAX_SRNG_V01,
+		.elem_size      = sizeof(struct wifi_drv_qmi_ipcc_information_v01),
+		.array_type       = VAR_LEN_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_ipcc_map_n_cfg_ind_msg_v01,
+					   ipcc_ce_info),
+		.ei_array       = wifi_drv_qmi_ipcc_information_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_ipcc_map_n_cfg_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_ipcc_map_n_cfg_req_msg_v01,
+					   status),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_misc_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wifi_drv_qmi_event_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_misc_req_msg_v01,
+					   event),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+struct qmi_elem_info wfds_misc_ind_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wifi_drv_qmi_event_v01),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct wfds_misc_ind_msg_v01,
+					   event),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type     = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};