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

Commit c72ebc5e authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "icnss2: Add support to load WPSS"

parents a1d26c8c 510ac340
Loading
Loading
Loading
Loading
+210 −10
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2020, 2021, The Linux Foundation.
 * All rights reserved.
 */

#define pr_fmt(fmt) "icnss2: " fmt
@@ -74,7 +75,7 @@
#define WLFW_TIMEOUT			msecs_to_jiffies(3000)

static struct icnss_priv *penv;

static struct work_struct wpss_loader;
uint64_t dynamic_feature_mask = ICNSS_DEFAULT_FEATURE_MASK;

#define ICNSS_EVENT_PENDING			2989
@@ -183,6 +184,8 @@ char *icnss_driver_event_to_str(enum icnss_driver_event_type type)
		return "QDSS_TRACE_FREE";
	case ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ:
		return "M3_DUMP_UPLOAD";
	case ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA:
		return "QDSS_TRACE_REQ_DATA";
	case ICNSS_DRIVER_EVENT_MAX:
		return "EVENT_MAX";
	}
@@ -833,6 +836,9 @@ static int icnss_driver_event_fw_init_done(struct icnss_priv *priv, void *data)

	icnss_pr_info("WLAN FW Initialization done: 0x%lx\n", priv->state);

	if (icnss_wlfw_qdss_dnld_send_sync(priv))
		icnss_pr_info("Failed to download qdss configuration file");

	if (test_bit(ICNSS_COLD_BOOT_CAL, &priv->state))
		ret = wlfw_wlan_mode_send_sync_msg(priv,
			(enum wlfw_driver_mode_enum_v01)ICNSS_CALIBRATION);
@@ -1008,6 +1014,25 @@ static inline int icnss_atomic_dec_if_greater_one(atomic_t *v)
	return dec;
}

static int icnss_qdss_trace_req_data_hdlr(struct icnss_priv *priv,
					  void *data)
{
	int ret = 0;
	struct icnss_qmi_event_qdss_trace_save_data *event_data = data;

	if (!priv)
		return -ENODEV;

	if (!data)
		return -EINVAL;

	ret = icnss_wlfw_qdss_data_send_sync(priv, event_data->file_name,
					     event_data->total_size);

	kfree(data);
	return ret;
}

static int icnss_event_soc_wake_request(struct icnss_priv *priv, void *data)
{
	int ret = 0;
@@ -1432,6 +1457,9 @@ static void icnss_driver_event_work(struct work_struct *work)
			break;
		case ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ:
			ret = icnss_m3_dump_upload_req_hdlr(priv, event->data);
		case ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA:
			ret = icnss_qdss_trace_req_data_hdlr(priv,
							     event->data);
			break;
		default:
			icnss_pr_err("Invalid Event type: %d", event->type);
@@ -2968,27 +2996,31 @@ void icnss_disallow_recursive_recovery(struct device *dev)
	icnss_pr_info("Recursive recovery disallowed for WLAN\n");
}

static void icnss_sysfs_create(struct icnss_priv *priv)
static int icnss_create_shutdown_sysfs(struct icnss_priv *priv)
{
	struct kobject *icnss_kobject;
	int error = 0;
	int ret = 0;

	atomic_set(&priv->is_shutdown, false);

	icnss_kobject = kobject_create_and_add("shutdown_wlan", kernel_kobj);
	if (!icnss_kobject) {
		icnss_pr_err("Unable to create kernel object");
		return;
		icnss_pr_err("Unable to create shutdown_wlan kernel object");
		return -EINVAL;
	}

	priv->icnss_kobject = icnss_kobject;

	error = sysfs_create_file(icnss_kobject, &icnss_sysfs_attribute.attr);
	if (error)
		icnss_pr_err("Unable to create icnss sysfs file");
	ret = sysfs_create_file(icnss_kobject, &icnss_sysfs_attribute.attr);
	if (ret) {
		icnss_pr_err("Unable to create icnss sysfs file err:%d", ret);
		return ret;
	}

static void icnss_sysfs_destroy(struct icnss_priv *priv)
	return ret;
}

static void icnss_destroy_shutdown_sysfs(struct icnss_priv *priv)
{
	struct kobject *icnss_kobject;

@@ -2997,6 +3029,173 @@ static void icnss_sysfs_destroy(struct icnss_priv *priv)
		kobject_put(icnss_kobject);
}

static ssize_t qdss_tr_start_store(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t count)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);

	wlfw_qdss_trace_start(priv);
	icnss_pr_dbg("Received QDSS start command\n");
	return count;
}

static ssize_t qdss_tr_stop_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *user_buf, size_t count)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);
	u32 option = 0;

	if (sscanf(user_buf, "%du", &option) != 1)
		return -EINVAL;

	wlfw_qdss_trace_stop(priv, option);
	icnss_pr_dbg("Received QDSS stop command\n");
	return count;
}

static ssize_t qdss_conf_download_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t count)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);

	icnss_wlfw_qdss_dnld_send_sync(priv);
	icnss_pr_dbg("Received QDSS download config command\n");
	return count;
}

static ssize_t hw_trc_override_store(struct device *dev,
				     struct device_attribute *attr,
				     const char *buf, size_t count)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);
	int tmp = 0;

	if (sscanf(buf, "%du", &tmp) != 1)
		return -EINVAL;

	priv->hw_trc_override = tmp;
	icnss_pr_dbg("Received QDSS hw_trc_override indication\n");
	return count;
}

static void icnss_wpss_load(struct work_struct *wpss_load_work)
{
	struct icnss_priv *priv = icnss_get_plat_priv();

	priv->subsys = subsystem_get("wpss");
	if (IS_ERR(priv->subsys))
		icnss_pr_err("Failed to load wpss subsys");
}

static inline void icnss_wpss_unload(struct icnss_priv *priv)
{
	if (priv->subsys) {
		subsystem_put(priv->subsys);
		priv->subsys = NULL;
	}
}

static ssize_t wpss_boot_store(struct device *dev,
			       struct device_attribute *attr,
			       const char *buf, size_t count)
{
	struct icnss_priv *priv = dev_get_drvdata(dev);
	int wpss_subsys = 0;

	if (priv->device_id != WCN6750_DEVICE_ID)
		return count;

	if (sscanf(buf, "%du", &wpss_subsys) != 1) {
		icnss_pr_err("Failed to read wpss_subsys info");
		return -EINVAL;
	}

	icnss_pr_dbg("WPSS Subsystem: %s", wpss_subsys ? "GET" : "PUT");

	if (wpss_subsys == 1)
		schedule_work(&wpss_loader);
	else if (wpss_subsys == 0)
		icnss_wpss_unload(priv);

	return count;
}

static DEVICE_ATTR_WO(qdss_tr_start);
static DEVICE_ATTR_WO(qdss_tr_stop);
static DEVICE_ATTR_WO(qdss_conf_download);
static DEVICE_ATTR_WO(hw_trc_override);
static DEVICE_ATTR_WO(wpss_boot);

static struct attribute *icnss_attrs[] = {
	&dev_attr_qdss_tr_start.attr,
	&dev_attr_qdss_tr_stop.attr,
	&dev_attr_qdss_conf_download.attr,
	&dev_attr_hw_trc_override.attr,
	&dev_attr_wpss_boot.attr,
	NULL,
};

static struct attribute_group icnss_attr_group = {
	.attrs = icnss_attrs,
};

static int icnss_create_sysfs_link(struct icnss_priv *priv)
{
	struct device *dev = &priv->pdev->dev;
	int ret;

	ret = sysfs_create_link(kernel_kobj, &dev->kobj, "icnss");
	if (ret) {
		icnss_pr_err("Failed to create icnss link, err = %d\n",
			     ret);
		goto out;
	}

	return 0;
out:
	return ret;
}

static void icnss_remove_sysfs_link(struct icnss_priv *priv)
{
	sysfs_remove_link(kernel_kobj, "icnss");
}

static int icnss_sysfs_create(struct icnss_priv *priv)
{
	int ret = 0;

	ret = devm_device_add_group(&priv->pdev->dev,
				    &icnss_attr_group);
	if (ret) {
		icnss_pr_err("Failed to create icnss device group, err = %d\n",
			     ret);
		goto out;
	}

	icnss_create_sysfs_link(priv);

	ret = icnss_create_shutdown_sysfs(priv);
	if (ret)
		goto remove_icnss_group;

	return 0;
remove_icnss_group:
	devm_device_remove_group(&priv->pdev->dev, &icnss_attr_group);
out:
	return ret;
}

static void icnss_sysfs_destroy(struct icnss_priv *priv)
{
	icnss_destroy_shutdown_sysfs(priv);
	icnss_remove_sysfs_link(priv);
	devm_device_remove_group(&priv->pdev->dev, &icnss_attr_group);
}

static int icnss_get_vbatt_info(struct icnss_priv *priv)
{
	struct adc_tm_chip *adc_tm_dev = NULL;
@@ -3488,6 +3687,7 @@ static int icnss_probe(struct platform_device *pdev)
		icnss_get_cpr_info(priv);
		icnss_get_smp2p_info(priv);
		set_bit(ICNSS_COLD_BOOT_CAL, &priv->state);
		INIT_WORK(&wpss_loader, icnss_wpss_load);
	}

	INIT_LIST_HEAD(&priv->icnss_tcdev_list);
+5 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, 2021, The Linux Foundation.
 * All rights reserved.
 */

#ifndef __MAIN_H__
@@ -57,6 +58,7 @@ enum icnss_driver_event_type {
	ICNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
	ICNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
	ICNSS_DRIVER_EVENT_M3_DUMP_UPLOAD_REQ,
	ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA,
	ICNSS_DRIVER_EVENT_MAX,
};

@@ -418,6 +420,7 @@ struct icnss_priv {
	bool is_ssr;
	bool smmu_s1_enable;
	struct kobject *icnss_kobject;
	void *subsys;
	atomic_t is_shutdown;
	u32 qdss_mem_seg_len;
	struct icnss_fw_mem qdss_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
@@ -432,6 +435,7 @@ struct icnss_priv {
	struct mutex tcdev_lock;
	bool is_chain1_supported;
	bool chain_reg_info_updated;
	u32 hw_trc_override;
};

struct icnss_reg_info {
+335 −7
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "main.h"
#include "qmi.h"
#include "debug.h"
#include "genl.h"

#define WLFW_SERVICE_WCN_INS_ID_V01	3
#define WLFW_SERVICE_INS_ID_V01		0
@@ -42,6 +43,8 @@
#define REGDB_FILE_NAME			"regdb.bin"
#define DUMMY_BDF_FILE_NAME		"bdwlan.dmy"

#define QDSS_TRACE_CONFIG_FILE "qdss_trace_config.cfg"

#define DEVICE_BAR_SIZE			0x200000
#define M3_SEGMENT_ADDR_MASK		0xFFFFFFFF

@@ -891,6 +894,238 @@ int icnss_wlfw_bdf_dnld_send_sync(struct icnss_priv *priv, u32 bdf_type)
	return ret;
}

int icnss_wlfw_qdss_data_send_sync(struct icnss_priv *priv, char *file_name,
				   u32 total_size)
{
	int ret = 0;
	struct wlfw_qdss_trace_data_req_msg_v01 *req;
	struct wlfw_qdss_trace_data_resp_msg_v01 *resp;
	unsigned char *p_qdss_trace_data_temp, *p_qdss_trace_data = NULL;
	unsigned int remaining;
	struct qmi_txn txn;

	icnss_pr_dbg("%s", __func__);

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
	if (!resp) {
		kfree(req);
		return -ENOMEM;
	}

	p_qdss_trace_data = kzalloc(total_size, GFP_KERNEL);
	if (!p_qdss_trace_data) {
		ret = ENOMEM;
		goto end;
	}

	remaining = total_size;
	p_qdss_trace_data_temp = p_qdss_trace_data;
	while (remaining && resp->end == 0) {
		ret = qmi_txn_init(&priv->qmi, &txn,
				   wlfw_qdss_trace_data_resp_msg_v01_ei, resp);

		if (ret < 0) {
			icnss_pr_err("Fail to init txn for QDSS trace resp %d\n",
				     ret);
			goto fail;
		}

		ret = qmi_send_request
			(&priv->qmi, NULL, &txn,
			 QMI_WLFW_QDSS_TRACE_DATA_REQ_V01,
			 WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN,
			 wlfw_qdss_trace_data_req_msg_v01_ei, req);

		if (ret < 0) {
			qmi_txn_cancel(&txn);
			icnss_pr_err("Fail to send QDSS trace data req %d\n",
				     ret);
			goto fail;
		}

		ret = qmi_txn_wait(&txn, priv->ctrl_params.qmi_timeout);

		if (ret < 0) {
			icnss_pr_err("QDSS trace resp wait failed with rc %d\n",
				     ret);
			goto fail;
		} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
			icnss_pr_err("QMI QDSS trace request rejected, result:%d error:%d\n",
				     resp->resp.result, resp->resp.error);
				     ret = -resp->resp.result;
			goto fail;
		} else {
			ret = 0;
		}

		icnss_pr_dbg("%s: response total size  %d data len %d",
			     __func__, resp->total_size, resp->data_len);

		if ((resp->total_size_valid == 1 &&
		     resp->total_size == total_size) &&
		    (resp->seg_id_valid == 1 && resp->seg_id == req->seg_id) &&
		    (resp->data_valid == 1 &&
		     resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01)) {
			memcpy(p_qdss_trace_data_temp,
			       resp->data, resp->data_len);
		} else {
			icnss_pr_err("%s: Unmatched qdss trace data, Expect total_size %u, seg_id %u, Recv total_size_valid %u, total_size %u, seg_id_valid %u, seg_id %u, data_len_valid %u, data_len %u",
				     __func__,
				     total_size, req->seg_id,
				     resp->total_size_valid,
				     resp->total_size,
				     resp->seg_id_valid,
				     resp->seg_id,
				     resp->data_valid,
				     resp->data_len);
			ret = -EINVAL;
			goto fail;
		}

		remaining -= resp->data_len;
		p_qdss_trace_data_temp += resp->data_len;
		req->seg_id++;
	}

	if (remaining == 0 && (resp->end_valid && resp->end)) {
		ret = icnss_genl_send_msg(p_qdss_trace_data,
					  ICNSS_GENL_MSG_TYPE_QDSS, file_name,
					  total_size);
		if (ret < 0) {
			icnss_pr_err("Fail to save QDSS trace data: %d\n",
				     ret);
		ret = -EINVAL;
		}
	} else {
		icnss_pr_err("%s: QDSS trace file corrupted: remaining %u, end_valid %u, end %u",
			     __func__,
			     remaining, resp->end_valid, resp->end);
		ret = -EINVAL;
	}

fail:
	kfree(p_qdss_trace_data);

end:
	kfree(req);
	kfree(resp);
	return ret;
}

int icnss_wlfw_qdss_dnld_send_sync(struct icnss_priv *priv)
{
	struct wlfw_qdss_trace_config_download_req_msg_v01 *req;
	struct wlfw_qdss_trace_config_download_resp_msg_v01 *resp;
	struct qmi_txn txn;
	char filename[ICNSS_MAX_FILE_NAME];
	const struct firmware *fw_entry = NULL;
	const u8 *temp;
	unsigned int remaining;
	int ret = 0;

	icnss_pr_dbg("Sending QDSS config download message, state: 0x%lx\n",
		     priv->state);

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
	if (!resp) {
		kfree(req);
		return -ENOMEM;
	}

	icnss_add_fw_prefix_name(priv, filename, QDSS_TRACE_CONFIG_FILE);
	ret = request_firmware(&fw_entry, filename,
			       &priv->pdev->dev);
	if (ret) {
		icnss_pr_err("Failed to load QDSS: %s\n",
			     filename);
		goto err_req_fw;
	}

	temp = fw_entry->data;
	remaining = fw_entry->size;

	icnss_pr_dbg("Downloading QDSS: %s, size: %u\n",
		     filename, remaining);

	while (remaining) {
		req->total_size_valid = 1;
		req->total_size = remaining;
		req->seg_id_valid = 1;
		req->data_valid = 1;
		req->end_valid = 1;

		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
		} else {
			req->data_len = remaining;
			req->end = 1;
		}

		memcpy(req->data, temp, req->data_len);

		ret = qmi_txn_init
			(&priv->qmi, &txn,
			 wlfw_qdss_trace_config_download_resp_msg_v01_ei,
			 resp);
		if (ret < 0) {
			icnss_pr_err("Failed to initialize txn for QDSS download request, err: %d\n",
				     ret);
			goto err_send;
		}

		ret = qmi_send_request
		      (&priv->qmi, NULL, &txn,
		       QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01,
		       WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
		       wlfw_qdss_trace_config_download_req_msg_v01_ei, req);
		if (ret < 0) {
			qmi_txn_cancel(&txn);
			icnss_pr_err("Failed to send respond QDSS download request, err: %d\n",
				     ret);
			goto err_send;
		}

		ret = qmi_txn_wait(&txn, priv->ctrl_params.qmi_timeout);
		if (ret < 0) {
			icnss_pr_err("Failed to wait for response of QDSS download request, err: %d\n",
				     ret);
			goto err_send;
		}

		if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
			icnss_pr_err("QDSS download request failed, result: %d, err: %d\n",
				     resp->resp.result, resp->resp.error);
			ret = -resp->resp.result;
			goto err_send;
		}

		remaining -= req->data_len;
		temp += req->data_len;
		req->seg_id++;
	}

	release_firmware(fw_entry);
	kfree(req);
	kfree(resp);
	return 0;

err_send:
	release_firmware(fw_entry);
err_req_fw:

	kfree(req);
	kfree(resp);
	return ret;
}

int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
		enum wlfw_driver_mode_enum_v01 mode)
{
@@ -980,6 +1215,94 @@ int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
	return ret;
}

static int wlfw_send_qdss_trace_mode_req
		(struct icnss_priv *priv,
		 enum wlfw_qdss_trace_mode_enum_v01 mode,
		 unsigned long long option)
{
	int rc = 0;
	int tmp = 0;
	struct wlfw_qdss_trace_mode_req_msg_v01 *req;
	struct wlfw_qdss_trace_mode_resp_msg_v01 *resp;
	struct qmi_txn txn;

	if (!priv)
		return -ENODEV;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
	if (!resp) {
		kfree(req);
		return -ENOMEM;
	}

	req->mode_valid = 1;
	req->mode = mode;
	req->option_valid = 1;
	req->option = option;

	tmp = priv->hw_trc_override;

	req->hw_trc_disable_override_valid = 1;
	req->hw_trc_disable_override =
	(tmp > QMI_PARAM_DISABLE_V01 ? QMI_PARAM_DISABLE_V01 :
		 (tmp < 0 ? QMI_PARAM_INVALID_V01 : tmp));

	icnss_pr_dbg("%s: mode %u, option %llu, hw_trc_disable_override: %u",
		     __func__, mode, option, req->hw_trc_disable_override);

	rc = qmi_txn_init(&priv->qmi, &txn,
			  wlfw_qdss_trace_mode_resp_msg_v01_ei, resp);
	if (rc < 0) {
		icnss_qmi_fatal_err("Fail to init txn for QDSS Mode resp %d\n",
				    rc);
		goto out;
	}

	rc = qmi_send_request(&priv->qmi, NULL, &txn,
			      QMI_WLFW_QDSS_TRACE_MODE_REQ_V01,
			      WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN,
			      wlfw_qdss_trace_mode_req_msg_v01_ei, req);
	if (rc < 0) {
		qmi_txn_cancel(&txn);
		icnss_qmi_fatal_err("Fail to send QDSS Mode req %d\n", rc);
		goto out;
	}

	rc = qmi_txn_wait(&txn, priv->ctrl_params.qmi_timeout);
	if (rc < 0) {
		icnss_qmi_fatal_err("QDSS Mode resp wait failed with rc %d\n",
				    rc);
		goto out;
	} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
		icnss_qmi_fatal_err(
			"QMI QDSS Mode request rejected, result:%d error:%d\n",
			resp->resp.result, resp->resp.error);
		rc = -resp->resp.result;
		goto out;
	}

out:
	kfree(resp);
	kfree(req);
	return rc;
}

int wlfw_qdss_trace_start(struct icnss_priv *priv)
{
	return wlfw_send_qdss_trace_mode_req(priv,
					     QMI_WLFW_QDSS_TRACE_ON_V01, 0);
}

int wlfw_qdss_trace_stop(struct icnss_priv *priv, unsigned long long option)
{
	return wlfw_send_qdss_trace_mode_req(priv, QMI_WLFW_QDSS_TRACE_OFF_V01,
					     option);
}

int wlfw_wlan_cfg_send_sync_msg(struct icnss_priv *priv,
				struct wlfw_wlan_cfg_req_msg_v01 *data)
{
@@ -1951,9 +2274,6 @@ static void wlfw_qdss_trace_save_ind_cb(struct qmi_handle *qmi,
		     ind_msg->source, ind_msg->total_size,
		     ind_msg->file_name_valid, ind_msg->file_name);

	if (ind_msg->source == 1)
		return;

	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
	if (!event_data)
		return;
@@ -1981,12 +2301,20 @@ static void wlfw_qdss_trace_save_ind_cb(struct qmi_handle *qmi,
	if (ind_msg->file_name_valid)
		strlcpy(event_data->file_name, ind_msg->file_name,
			QDSS_TRACE_FILE_NAME_MAX + 1);
	else
		strlcpy(event_data->file_name, "qdss_trace",
			QDSS_TRACE_FILE_NAME_MAX + 1);

	if (ind_msg->source == 1) {
		if (!ind_msg->file_name_valid)
			strlcpy(event_data->file_name, "qdss_trace_wcss_etb",
				QDSS_TRACE_FILE_NAME_MAX + 1);
	icnss_driver_event_post(priv, ICNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA,
				0, event_data);
	} else {
		if (!ind_msg->file_name_valid)
			strlcpy(event_data->file_name, "qdss_trace_ddr",
				QDSS_TRACE_FILE_NAME_MAX + 1);
	icnss_driver_event_post(priv, ICNSS_DRIVER_EVENT_QDSS_TRACE_SAVE,
				0, event_data);
	}

	return;

+10 −0
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@ struct icnss_m3_upload_segments_req_data {
	struct icnss_m3_segment m3_segment[M3_SEGMENTS_SIZE_MAX];
};

struct icnss_qmi_event_qdss_trace_req_data {
	u32 total_size;
	char file_name[QDSS_TRACE_FILE_NAME_MAX + 1];
};

#ifndef CONFIG_ICNSS2_QMI

static inline int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
@@ -201,6 +206,11 @@ int wlfw_device_info_send_msg(struct icnss_priv *priv);
int wlfw_wlan_mode_send_sync_msg(struct icnss_priv *priv,
				 enum wlfw_driver_mode_enum_v01 mode);
int icnss_wlfw_bdf_dnld_send_sync(struct icnss_priv *priv, u32 bdf_type);
int icnss_wlfw_qdss_dnld_send_sync(struct icnss_priv *priv);
int icnss_wlfw_qdss_data_send_sync(struct icnss_priv *priv, char *file_name,
				   u32 total_size);
int wlfw_qdss_trace_start(struct icnss_priv *priv);
int wlfw_qdss_trace_stop(struct icnss_priv *priv, unsigned long long option);
int wlfw_qdss_trace_mem_info_send_sync(struct icnss_priv *priv);
int wlfw_power_save_send_msg(struct icnss_priv *priv,
			     enum wlfw_power_save_mode_v01 mode);