Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9aca58d authored by Yuanyuan Liu's avatar Yuanyuan Liu Committed by Hardik Kantilal Patel
Browse files

icnss: Add support for WLAN firmware service



iCNSS driver is a client to WLAN firmware service started at Q6.
Initial control messages to WLAN firmware is exchanged through QMI
interface. This change also adds the APIs required for WLAN driver
to enable and disable WLAN at firmware.

Change-Id: If992dbae80f12e1a976bc6e612053cacba1bc716
CRs-Fixed: 914429
Signed-off-by: default avatarYuanyuan Liu <yuanliu@codeaurora.org>
parent f5d3db32
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ obj-$(CONFIG_MSM_SERVICE_NOTIFIER) += service-notifier.o
obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o sysmon-qmi.o
obj-$(CONFIG_MSM_SECURE_BUFFER) += secure_buffer.o
obj-$(CONFIG_TRACER_PKT) += tracer_pkt.o
obj-$(CONFIG_ICNSS) += icnss.o
obj-$(CONFIG_ICNSS) += icnss.o wlan_firmware_service_v01.o
obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o
obj-$(CONFIG_MSM_SERVICE_LOCATOR) += service-locator.o
obj-$(CONFIG_MSM_PACMAN)        += msm_pacman.o
+570 −5
Original line number Diff line number Diff line
@@ -19,8 +19,52 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/qmi_encdec.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/msm_qmi_interface.h>

#include "wlan_firmware_service_v01.h"

enum icnss_qmi_event_type {
	ICNSS_QMI_EVENT_SERVER_ARRIVE,
	ICNSS_QMI_EVENT_SERVER_EXIT,
	ICNSS_QMI_EVENT_FW_READY_IND,
};

struct icnss_qmi_event {
	struct list_head list;
	enum icnss_qmi_event_type type;
	void *data;
};

#define ICNSS_PANIC			1
#define WLFW_TIMEOUT_MS			3000
#define WLFW_SERVICE_INS_ID_V01		0
#define ICNSS_WLFW_QMI_CONNECTED	BIT(0)
#define ICNSS_FW_READY			BIT(1)

#define ICNSS_IS_WLFW_QMI_CONNECTED(_state) \
		((_state) & ICNSS_WLFW_QMI_CONNECTED)
#define ICNSS_IS_FW_READY(_state) ((_state) & ICNSS_FW_READY)

#ifdef ICNSS_PANIC
#define ICNSS_ASSERT(_condition) do {			\
		if (!(_condition)) {				\
			pr_err("ICNSS ASSERT in %s Line %d\n",	\
				__func__, __LINE__);		\
			BUG_ON(1);				\
		}						\
	} while (0)
#else
#define ICNSS_ASSERT(_condition) do {			\
		if (!(_condition)) {				\
			pr_err("ICNSS ASSERT in %s Line %d\n",	\
				__func__, __LINE__);		\
			WARN_ON(1);				\
		}						\
	} while (0)
#endif

struct ce_irq_list {
	int irq;
@@ -34,8 +78,439 @@ static struct {
	u32 ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
	phys_addr_t mem_base_pa;
	void __iomem *mem_base_va;
	struct qmi_handle *wlfw_clnt;
	struct list_head qmi_event_list;
	spinlock_t qmi_event_lock;
	struct work_struct qmi_event_work;
	struct work_struct qmi_recv_msg_work;
	struct workqueue_struct *qmi_event_wq;
	uint32_t state;
	u32 board_id;
	u32 num_peers;
	u32 mac_version;
	char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
} *penv;

static int icnss_qmi_event_post(enum icnss_qmi_event_type type, void *data)
{
	struct icnss_qmi_event *event = NULL;
	unsigned long flags;
	int gfp = GFP_KERNEL;

	if (in_interrupt() || irqs_disabled())
		gfp = GFP_ATOMIC;

	event = kzalloc(sizeof(*event), gfp);
	if (event == NULL)
		return -ENOMEM;

	event->type = type;
	event->data = data;
	spin_lock_irqsave(&penv->qmi_event_lock, flags);
	list_add_tail(&event->list, &penv->qmi_event_list);
	spin_unlock_irqrestore(&penv->qmi_event_lock, flags);

	queue_work(penv->qmi_event_wq, &penv->qmi_event_work);

	return 0;
}

static int wlfw_ind_register_send_sync_msg(void)
{
	int ret;
	struct wlfw_ind_register_req_msg_v01 req;
	struct wlfw_ind_register_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;

	if (!penv || !penv->wlfw_clnt) {
		ret = -ENODEV;
		goto out;
	}

	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	req.fw_ready_enable_valid = 1;
	req.fw_ready_enable = 1;

	req_desc.max_msg_len = WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_IND_REGISTER_REQ_V01;
	req_desc.ei_array = wlfw_ind_register_req_msg_v01_ei;

	resp_desc.max_msg_len = WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_WLFW_IND_REGISTER_RESP_V01;
	resp_desc.ei_array = wlfw_ind_register_resp_msg_v01_ei;

	ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
				&resp_desc, &resp, sizeof(resp),
				WLFW_TIMEOUT_MS);
	if (ret < 0) {
		pr_err("%s: send req failed %d\n", __func__, ret);
		goto out;
	}

	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
		pr_err("%s: QMI request failed %d %d\n",
		       __func__, resp.resp.result, resp.resp.error);
		ret = resp.resp.result;
		goto out;
	}
out:
	return ret;
}

static int wlfw_cap_send_sync_msg(void)
{
	int ret;
	struct wlfw_cap_req_msg_v01 req;
	struct wlfw_cap_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;

	if (!penv || !penv->wlfw_clnt) {
		ret = -ENODEV;
		goto out;
	}

	memset(&resp, 0, sizeof(resp));

	req_desc.max_msg_len = WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_CAP_REQ_V01;
	req_desc.ei_array = wlfw_cap_req_msg_v01_ei;

	resp_desc.max_msg_len = WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_WLFW_CAP_RESP_V01;
	resp_desc.ei_array = wlfw_cap_resp_msg_v01_ei;

	ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
				&resp_desc, &resp, sizeof(resp),
				WLFW_TIMEOUT_MS);
	if (ret < 0) {
		pr_err("%s: send req failed %d\n", __func__, ret);
		goto out;
	}

	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
		pr_err("%s: QMI request failed %d %d\n",
		       __func__, resp.resp.result, resp.resp.error);
		ret = resp.resp.result;
		goto out;
	}

	/* store cap locally */
	if (resp.board_id_valid)
		penv->board_id = resp.board_id;
	if (resp.num_peers_valid)
		penv->num_peers = resp.num_peers;
	if (resp.mac_version_valid)
		penv->mac_version = resp.mac_version;
	if (resp.fw_version_valid)
		strlcpy(penv->fw_version, resp.fw_version,
			QMI_WLFW_MAX_STR_LEN_V01 + 1);

	pr_debug("%s: board_id:0x%0x num_peers: %d mac_version: 0x%0x fw_version: %s",
		__func__, penv->board_id, penv->num_peers,
		penv->mac_version, penv->fw_version);
out:
	return ret;
}

static int wlfw_wlan_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
{
	int ret;
	struct wlfw_wlan_mode_req_msg_v01 req;
	struct wlfw_wlan_mode_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;

	if (!penv || !penv->wlfw_clnt) {
		ret = -ENODEV;
		goto out;
	}

	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	req.mode = mode;

	req_desc.max_msg_len = WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_WLAN_MODE_REQ_V01;
	req_desc.ei_array = wlfw_wlan_mode_req_msg_v01_ei;

	resp_desc.max_msg_len = WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_WLFW_WLAN_MODE_RESP_V01;
	resp_desc.ei_array = wlfw_wlan_mode_resp_msg_v01_ei;

	ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
				&resp_desc, &resp, sizeof(resp),
				WLFW_TIMEOUT_MS);
	if (ret < 0) {
		pr_err("%s: send req failed %d\n", __func__, ret);
		goto out;
	}

	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
		pr_err("%s: QMI request failed %d %d\n",
		       __func__, resp.resp.result, resp.resp.error);
		ret = resp.resp.result;
		goto out;
	}
out:
	return ret;
}

static int wlfw_wlan_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
{
	int ret;
	struct wlfw_wlan_cfg_req_msg_v01 req;
	struct wlfw_wlan_cfg_resp_msg_v01 resp;
	struct msg_desc req_desc, resp_desc;

	if (!penv || !penv->wlfw_clnt) {
		return -ENODEV;
		goto out;
	}

	memset(&req, 0, sizeof(req));
	memset(&resp, 0, sizeof(resp));

	memcpy(&req, data, sizeof(req));

	req_desc.max_msg_len = WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN;
	req_desc.msg_id = QMI_WLFW_WLAN_CFG_REQ_V01;
	req_desc.ei_array = wlfw_wlan_cfg_req_msg_v01_ei;

	resp_desc.max_msg_len = WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN;
	resp_desc.msg_id = QMI_WLFW_WLAN_CFG_RESP_V01;
	resp_desc.ei_array = wlfw_wlan_cfg_resp_msg_v01_ei;

	ret = qmi_send_req_wait(penv->wlfw_clnt, &req_desc, &req, sizeof(req),
				&resp_desc, &resp, sizeof(resp),
				WLFW_TIMEOUT_MS);
	if (ret < 0) {
		pr_err("%s: send req failed %d\n", __func__, ret);
		goto out;
	}

	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
		pr_err("%s: QMI request failed %d %d\n",
		       __func__, resp.resp.result, resp.resp.error);
		ret = resp.resp.result;
		goto out;
	}
out:
	return ret;
}

static void icnss_qmi_wlfw_clnt_notify_work(struct work_struct *work)
{
	int ret;

	if (!penv || !penv->wlfw_clnt)
		return;

	do {
		pr_debug("%s: Received Event\n", __func__);
	} while ((ret = qmi_recv_msg(penv->wlfw_clnt)) == 0);

	if (ret != -ENOMSG)
		pr_err("%s: Error receiving message\n", __func__);
}

static void icnss_qmi_wlfw_clnt_notify(struct qmi_handle *handle,
			     enum qmi_event_type event, void *notify_priv)
{
	if (!penv || !penv->wlfw_clnt)
		return;

	switch (event) {
	case QMI_RECV_MSG:
		schedule_work(&penv->qmi_recv_msg_work);
		break;
	default:
		pr_debug("%s: Received Event:  %d\n", __func__, event);
		break;
	}
}

static void icnss_qmi_wlfw_clnt_ind(struct qmi_handle *handle,
			  unsigned int msg_id, void *msg,
			  unsigned int msg_len, void *ind_cb_priv)
{
	if (!penv)
		return;

	pr_debug("%s: Received Ind 0x%x\n", __func__, msg_id);

	switch (msg_id) {
	case QMI_WLFW_FW_READY_IND_V01:
		icnss_qmi_event_post(ICNSS_QMI_EVENT_FW_READY_IND, NULL);
		break;
	default:
		pr_err("%s: Invalid msg_id 0x%x\n", __func__, msg_id);
		break;
	}
}

static int icnss_qmi_event_server_arrive(void *data)
{
	int ret = 0;

	if (!penv)
		return -ENODEV;

	penv->wlfw_clnt = qmi_handle_create(icnss_qmi_wlfw_clnt_notify, penv);
	if (!penv->wlfw_clnt) {
		pr_err("%s: QMI client handle alloc failed\n", __func__);
		ret = -ENOMEM;
		goto out;
	}

	ret = qmi_connect_to_service(penv->wlfw_clnt,
					WLFW_SERVICE_ID_V01,
					WLFW_SERVICE_VERS_V01,
					WLFW_SERVICE_INS_ID_V01);
	if (ret < 0) {
		pr_err("%s: Server not found : %d\n", __func__, ret);
		goto fail;
	}

	ret = qmi_register_ind_cb(penv->wlfw_clnt,
				  icnss_qmi_wlfw_clnt_ind, penv);
	if (ret < 0) {
		pr_err("Failed to register indication callback: %d\n",
		       ret);
		goto fail;
	}

	penv->state |= ICNSS_WLFW_QMI_CONNECTED;

	pr_info("%s: QMI Server Connected\n", __func__);

	ret = wlfw_ind_register_send_sync_msg();
	if (ret < 0) {
		pr_err("Failed to send indication message: %d\n",
		       ret);
		goto out;
	}

	ret = wlfw_cap_send_sync_msg();
	if (ret < 0) {
		pr_err("Failed to get capability: %d\n",
		       ret);
		goto out;
	}
	return ret;
fail:
	qmi_handle_destroy(penv->wlfw_clnt);
	penv->wlfw_clnt = NULL;
out:
	ICNSS_ASSERT(0);
	return ret;
}

static int icnss_qmi_event_server_exit(void *data)
{
	if (!penv || !penv->wlfw_clnt)
		return -ENODEV;

	pr_info("%s: QMI Service Disconnected\n", __func__);

	qmi_handle_destroy(penv->wlfw_clnt);
	penv->state = 0;
	penv->wlfw_clnt = NULL;

	return 0;
}

static int icnss_qmi_event_fw_ready_ind(void *data)
{
	int ret = 0;

	if (!penv)
		return -ENODEV;

	penv->state |= ICNSS_FW_READY;

	if (!penv->pdev) {
		pr_err("%s: Device is not ready\n", __func__);
		ret = -ENODEV;
		goto out;
	}
	if (!penv->ops || !penv->ops->probe) {
		pr_err("%s: WLAN driver is not registed yet\n", __func__);
		ret = -ENOENT;
		goto out;
	}

	ret = penv->ops->probe(&penv->pdev->dev);
	if (ret < 0)
		pr_err("%s: Driver probe failed: %d\n", __func__, ret);
out:
	return ret;
}

static int icnss_qmi_wlfw_clnt_svc_event_notify(struct notifier_block *this,
					       unsigned long code,
					       void *_cmd)
{
	int ret = 0;

	if (!penv)
		return -ENODEV;

	pr_debug("Event Notify: code: %ld", code);

	switch (code) {
	case QMI_SERVER_ARRIVE:
		ret = icnss_qmi_event_post(ICNSS_QMI_EVENT_SERVER_ARRIVE, NULL);
		break;

	case QMI_SERVER_EXIT:
		ret = icnss_qmi_event_post(ICNSS_QMI_EVENT_SERVER_EXIT, NULL);
		break;
	default:
		pr_debug("Invalid code: %ld", code);
		break;
	}
	return ret;
}

static void icnss_qmi_wlfw_event_work(struct work_struct *work)
{
	struct icnss_qmi_event *event;
	unsigned long flags;

	spin_lock_irqsave(&penv->qmi_event_lock, flags);

	while (!list_empty(&penv->qmi_event_list)) {
		event = list_first_entry(&penv->qmi_event_list,
					 struct icnss_qmi_event, list);
		list_del(&event->list);
		spin_unlock_irqrestore(&penv->qmi_event_lock, flags);

		switch (event->type) {
		case ICNSS_QMI_EVENT_SERVER_ARRIVE:
			icnss_qmi_event_server_arrive(event->data);
			break;
		case ICNSS_QMI_EVENT_SERVER_EXIT:
			icnss_qmi_event_server_exit(event->data);
			break;
		case ICNSS_QMI_EVENT_FW_READY_IND:
			icnss_qmi_event_fw_ready_ind(event->data);
			break;
		default:
			pr_debug("Invalid Event type: %d", event->type);
			break;
		}
		kfree(event);
		spin_lock_irqsave(&penv->qmi_event_lock, flags);
	}
	spin_unlock_irqrestore(&penv->qmi_event_lock, flags);
}

static struct notifier_block wlfw_clnt_nb = {
	.notifier_call = icnss_qmi_wlfw_clnt_svc_event_notify,
};

int icnss_register_driver(struct icnss_driver_ops *ops)
{
	struct platform_device *pdev;
@@ -60,7 +535,7 @@ int icnss_register_driver(struct icnss_driver_ops *ops)
	penv->ops = ops;

	/* check for all conditions before invoking probe */
	if (penv->ops->probe)
	if (ICNSS_IS_FW_READY(penv->state) && penv->ops->probe)
		ret = penv->ops->probe(&pdev->dev);

out:
@@ -269,15 +744,78 @@ int icnss_get_soc_info(struct icnss_soc_info *info)
EXPORT_SYMBOL(icnss_get_soc_info);

int icnss_wlan_enable(struct icnss_wlan_enable_cfg *config,
		enum icnss_driver_mode mode)
		      enum icnss_driver_mode mode,
		      const char *host_version)
{
	return 0;
	struct wlfw_wlan_cfg_req_msg_v01 req;
	u32 i;
	int ret;

	memset(&req, 0, sizeof(req));

	if (mode == ICNSS_WALTEST)
		goto skip;
	else if (!config || !host_version) {
		pr_err("%s: Invalid cfg pointer\n", __func__);
		ret = -EINVAL;
		goto out;
	}

	req.host_version_valid = 1;
	strlcpy(req.host_version, host_version,
		QMI_WLFW_MAX_STR_LEN_V01 + 1);

	req.tgt_cfg_valid = 1;
	if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
		req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
	else
		req.tgt_cfg_len = config->num_ce_tgt_cfg;
	for (i = 0; i < req.tgt_cfg_len; i++) {
		req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
		req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
		req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
		req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
		req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
	}

	req.svc_cfg_valid = 1;
	if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
		req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
	else
		req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
	for (i = 0; i < req.svc_cfg_len; i++) {
		req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
		req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
		req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
	}

	req.shadow_reg_valid = 1;
	if (config->num_shadow_reg_cfg >
	    QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
		req.shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
	else
		req.shadow_reg_len = config->num_shadow_reg_cfg;

	memcpy(req.shadow_reg, config->shadow_reg_cfg,
	       sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req.shadow_reg_len);

	ret = wlfw_wlan_cfg_send_sync_msg(&req);
	if (ret) {
		pr_err("%s: Failed to send cfg, ret = %d\n", __func__, ret);
		goto out;
	}
skip:
	ret = wlfw_wlan_mode_send_sync_msg(mode);
	if (ret)
		pr_err("%s: Failed to send mode, ret = %d\n", __func__, ret);
out:
	return ret;
}
EXPORT_SYMBOL(icnss_wlan_enable);

int icnss_wlan_disable(enum icnss_driver_mode mode)
{
	return 0;
	return wlfw_wlan_mode_send_sync_msg(QMI_WLFW_OFF_V01);
}
EXPORT_SYMBOL(icnss_wlan_disable);

@@ -297,7 +835,6 @@ EXPORT_SYMBOL(icnss_get_ce_id);
static int icnss_probe(struct platform_device *pdev)
{
	int ret = 0;
	int len = 0;
	struct resource *res;
	int i;

@@ -335,6 +872,27 @@ static int icnss_probe(struct platform_device *pdev)
		}
	}

	penv->qmi_event_wq = alloc_workqueue("icnss_qmi_event", 0, 0);
	if (!penv->qmi_event_wq) {
		pr_err("%s: workqueue creation failed\n", __func__);
		ret = -EFAULT;
		goto out;
	}

	INIT_WORK(&penv->qmi_event_work, icnss_qmi_wlfw_event_work);
	INIT_WORK(&penv->qmi_recv_msg_work, icnss_qmi_wlfw_clnt_notify_work);
	INIT_LIST_HEAD(&penv->qmi_event_list);

	ret = qmi_svc_event_notifier_register(WLFW_SERVICE_ID_V01,
					      WLFW_SERVICE_VERS_V01,
					      WLFW_SERVICE_INS_ID_V01,
					      &wlfw_clnt_nb);
	if (ret < 0) {
		pr_err("%s: notifier register failed\n", __func__);
		destroy_workqueue(penv->qmi_event_wq);
		goto out;
	}

	pr_debug("icnss: Platform driver probed successfully\n");
out:
	return ret;
@@ -342,6 +900,13 @@ out:

static int icnss_remove(struct platform_device *pdev)
{
	qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01,
					  WLFW_SERVICE_VERS_V01,
					  WLFW_SERVICE_INS_ID_V01,
					  &wlfw_clnt_nb);
	if (penv->qmi_event_wq)
		destroy_workqueue(penv->qmi_event_wq);

	return 0;
}

+979 −0

File added.

Preview size limit exceeded, changes collapsed.

+274 −0
Original line number Diff line number Diff line
 /* Copyright (c) 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 WLAN_FIRMWARE_SERVICE_V01_H
#define WLAN_FIRMWARE_SERVICE_V01_H

#define WLFW_SERVICE_ID_V01 0x45
#define WLFW_SERVICE_VERS_V01 0x01

#define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
#define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
#define QMI_WLFW_CAP_RESP_V01 0x0024
#define QMI_WLFW_BDF_DOWNLOAD_REQ_V01 0x0025
#define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027
#define QMI_WLFW_WLAN_MODE_RESP_V01 0x0022
#define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
#define QMI_WLFW_BDF_DOWNLOAD_RESP_V01 0x0025
#define QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01 0x002A
#define QMI_WLFW_FW_READY_IND_V01 0x0021
#define QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01 0x0028
#define QMI_WLFW_CAP_REQ_V01 0x0024
#define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
#define QMI_WLFW_WLAN_MODE_REQ_V01 0x0022
#define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
#define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLFW_WLAN_CFG_RESP_V01 0x0023
#define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
#define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020

#define QMI_WLFW_MAX_NUM_CAL_V01 5
#define QMI_WLFW_MAX_DATA_SIZE_V01 6144
#define QMI_WLFW_MAX_NUM_CE_V01 12
#define QMI_WLFW_MAX_STR_LEN_V01 16
#define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24
#define QMI_WLFW_MAX_NUM_SVC_V01 24

enum wlfw_driver_mode_enum_v01 {
	WLFW_DRIVER_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
	QMI_WLFW_MISSION_V01 = 0,
	QMI_WLFW_FTM_V01 = 1,
	QMI_WLFW_EPPING_V01 = 2,
	QMI_WLFW_WALTEST_V01 = 3,
	QMI_WLFW_OFF_V01 = 4,
	WLFW_DRIVER_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
};

enum wlfw_cal_temp_id_enum_v01 {
	WLFW_CAL_TEMP_ID_ENUM_MIN_VAL_V01 = INT_MIN,
	QMI_WLFW_CAL_TEMP_IDX_0_V01 = 0,
	QMI_WLFW_CAL_TEMP_IDX_1_V01 = 1,
	QMI_WLFW_CAL_TEMP_IDX_2_V01 = 2,
	QMI_WLFW_CAL_TEMP_IDX_3_V01 = 3,
	QMI_WLFW_CAL_TEMP_IDX_4_V01 = 4,
	WLFW_CAL_TEMP_ID_ENUM_MAX_VAL_V01 = INT_MAX,
};

enum wlfw_pipedir_enum_v01 {
	WLFW_PIPEDIR_ENUM_MIN_VAL_V01 = INT_MIN,
	QMI_WLFW_PIPEDIR_NONE_V01 = 0,
	QMI_WLFW_PIPEDIR_IN_V01 = 1,
	QMI_WLFW_PIPEDIR_OUT_V01 = 2,
	QMI_WLFW_PIPEDIR_INOUT_V01 = 3,
	WLFW_PIPEDIR_ENUM_MAX_VAL_V01 = INT_MAX,
};

#define QMI_WLFW_CE_ATTR_FLAGS_V01 ((uint32_t)0x00)
#define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((uint32_t)0x01)
#define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((uint32_t)0x02)
#define QMI_WLFW_CE_ATTR_SWIZZLE_DESCRIPTORS_V01 ((uint32_t)0x04)
#define QMI_WLFW_CE_ATTR_DISABLE_INTR_V01 ((uint32_t)0x08)
#define QMI_WLFW_CE_ATTR_ENABLE_POLL_V01 ((uint32_t)0x10)

struct wlfw_ce_tgt_pipe_cfg_s_v01 {
	uint32_t pipe_num;
	enum wlfw_pipedir_enum_v01 pipe_dir;
	uint32_t nentries;
	uint32_t nbytes_max;
	uint32_t flags;
};

struct wlfw_ce_svc_pipe_cfg_s_v01 {
	uint32_t service_id;
	enum wlfw_pipedir_enum_v01 pipe_dir;
	uint32_t pipe_num;
};

struct wlfw_shadow_reg_cfg_s_v01 {
	uint16_t id;
	uint16_t offset;
};

struct wlfw_ind_register_req_msg_v01 {
	uint8_t fw_ready_enable_valid;
	uint8_t fw_ready_enable;
	uint8_t initiate_cal_download_enable_valid;
	uint8_t initiate_cal_download_enable;
	uint8_t initiate_cal_update_enable_valid;
	uint8_t initiate_cal_update_enable;
};
#define WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN 12
extern struct elem_info wlfw_ind_register_req_msg_v01_ei[];

struct wlfw_ind_register_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_IND_REGISTER_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_ind_register_resp_msg_v01_ei[];

struct wlfw_fw_ready_ind_msg_v01 {
	char placeholder;
};
#define WLFW_FW_READY_IND_MSG_V01_MAX_MSG_LEN 0
extern struct elem_info wlfw_fw_ready_ind_msg_v01_ei[];

struct wlfw_wlan_mode_req_msg_v01 {
	enum wlfw_driver_mode_enum_v01 mode;
};
#define WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_wlan_mode_req_msg_v01_ei[];

struct wlfw_wlan_mode_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_MODE_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_wlan_mode_resp_msg_v01_ei[];

struct wlfw_wlan_cfg_req_msg_v01 {
	uint8_t host_version_valid;
	char host_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
	uint8_t tgt_cfg_valid;
	uint32_t tgt_cfg_len;
	struct wlfw_ce_tgt_pipe_cfg_s_v01 tgt_cfg[QMI_WLFW_MAX_NUM_CE_V01];
	uint8_t svc_cfg_valid;
	uint32_t svc_cfg_len;
	struct wlfw_ce_svc_pipe_cfg_s_v01 svc_cfg[QMI_WLFW_MAX_NUM_SVC_V01];
	uint8_t shadow_reg_valid;
	uint32_t shadow_reg_len;
	struct wlfw_shadow_reg_cfg_s_v01 shadow_reg[QMI_WLFW_MAX_NUM_SHADOW_REG_V01];
};
#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 655
extern struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[];

struct wlfw_wlan_cfg_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_WLAN_CFG_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_wlan_cfg_resp_msg_v01_ei[];

struct wlfw_cap_req_msg_v01 {
	char placeholder;
};
#define WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN 0
extern struct elem_info wlfw_cap_req_msg_v01_ei[];

struct wlfw_cap_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
	uint8_t board_id_valid;
	uint32_t board_id;
	uint8_t num_peers_valid;
	uint32_t num_peers;
	uint8_t mac_version_valid;
	uint32_t mac_version;
	uint8_t fw_version_valid;
	char fw_version[QMI_WLFW_MAX_STR_LEN_V01 + 1];
};
#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 47
extern struct elem_info wlfw_cap_resp_msg_v01_ei[];

struct wlfw_bdf_download_req_msg_v01 {
	uint8_t valid;
	uint8_t file_id_valid;
	enum wlfw_cal_temp_id_enum_v01 file_id;
	uint8_t total_size_valid;
	uint32_t total_size;
	uint8_t seg_id_valid;
	uint32_t seg_id;
	uint8_t data_valid;
	uint32_t data_len;
	uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
	uint8_t end_valid;
	uint8_t end;
};
#define WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6178
extern struct elem_info wlfw_bdf_download_req_msg_v01_ei[];

struct wlfw_bdf_download_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_BDF_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_bdf_download_resp_msg_v01_ei[];

struct wlfw_cal_report_req_msg_v01 {
	uint32_t meta_data_len;
	enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01];
};
#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 24
extern struct elem_info wlfw_cal_report_req_msg_v01_ei[];

struct wlfw_cal_report_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_REPORT_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_cal_report_resp_msg_v01_ei[];

struct wlfw_initiate_cal_download_ind_msg_v01 {
	enum wlfw_cal_temp_id_enum_v01 cal_id;
};
#define WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_initiate_cal_download_ind_msg_v01_ei[];

struct wlfw_cal_download_req_msg_v01 {
	uint8_t valid;
	uint8_t file_id_valid;
	enum wlfw_cal_temp_id_enum_v01 file_id;
	uint8_t total_size_valid;
	uint32_t total_size;
	uint8_t seg_id_valid;
	uint32_t seg_id;
	uint8_t data_valid;
	uint32_t data_len;
	uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
	uint8_t end_valid;
	uint8_t end;
};
#define WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN 6178
extern struct elem_info wlfw_cal_download_req_msg_v01_ei[];

struct wlfw_cal_download_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};
#define WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN 7
extern struct elem_info wlfw_cal_download_resp_msg_v01_ei[];

struct wlfw_initiate_cal_update_ind_msg_v01 {
	enum wlfw_cal_temp_id_enum_v01 cal_id;
	uint32_t total_size;
};
#define WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN 14
extern struct elem_info wlfw_initiate_cal_update_ind_msg_v01_ei[];

struct wlfw_cal_update_req_msg_v01 {
	enum wlfw_cal_temp_id_enum_v01 cal_id;
	uint32_t seg_id;
};
#define WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN 14
extern struct elem_info wlfw_cal_update_req_msg_v01_ei[];

struct wlfw_cal_update_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
	uint8_t file_id_valid;
	enum wlfw_cal_temp_id_enum_v01 file_id;
	uint8_t total_size_valid;
	uint32_t total_size;
	uint8_t seg_id_valid;
	uint32_t seg_id;
	uint8_t data_valid;
	uint32_t data_len;
	uint8_t data[QMI_WLFW_MAX_DATA_SIZE_V01];
	uint8_t end_valid;
	uint8_t end;
};
#define WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN 6181
extern struct elem_info wlfw_cal_update_resp_msg_v01_ei[];

#endif
+11 −1

File changed.

Preview size limit exceeded, changes collapsed.