--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -915,6 +915,9 @@ int ath11k_core_qmi_firmware_ready(struc
 	}
 #endif
 	ath11k_hif_irq_enable(ab);
+
+	ath11k_config_qdss(ab);
+
 	mutex_unlock(&ab->core_lock);
 
 	return 0;
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -928,6 +928,7 @@ struct ath11k_base *ath11k_core_alloc(st
 void ath11k_core_free(struct ath11k_base *ath11k);
 int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
 			  struct ath11k_board_data *bd);
+int ath11k_config_qdss(struct ath11k_base *ab);
 void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
 int ath11k_core_check_dt(struct ath11k_base *ath11k);
 
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -20,6 +20,194 @@ module_param_named(cold_boot_cal, ath11k
 MODULE_PARM_DESC(cold_boot_cal,
 		 "Decrease the channel switch time but increase the driver load time (Default: true)");
 
+unsigned int enable_qdss_trace = 1;
+module_param(enable_qdss_trace, uint, 0644);
+MODULE_PARM_DESC(enable_qdss_trace, "qdss trace enable:1 disable:0");
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_req_msg_v01_ei[] = {
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset         = offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				total_size_valid),
+	},
+	{
+		.data_type	= QMI_UNSIGNED_4_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u32),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				total_size),
+	},
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				seg_id_valid),
+	},
+	{
+		.data_type	= QMI_UNSIGNED_4_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u32),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				seg_id),
+	},
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x12,
+		.offset         = offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				data_valid),
+	},
+	{
+		.data_type	= QMI_DATA_LEN,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u16),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x12,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				data_len),
+	},
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= QMI_WLANFW_MAX_DATA_SIZE_V01,
+		.elem_size	= sizeof(u8),
+		.array_type	= VAR_LEN_ARRAY,
+		.tlv_type	= 0x12,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				data),
+	},
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x13,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				end_valid),
+	},
+	{
+		.data_type	= QMI_UNSIGNED_1_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x13,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+				end),
+	},
+	{
+		.data_type	= QMI_EOTI,
+		.array_type	= NO_ARRAY,
+		.tlv_type	= QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_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
+				qmi_wlanfw_qdss_trace_config_download_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 qmi_wlanfw_qdss_trace_mode_req_msg_v01_ei[] = {
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+				mode_valid),
+	},
+	{
+		.data_type	= QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len	= 1,
+		.elem_size	= sizeof(enum wlfw_qdss_trace_mode_enum_v01),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x10,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+				mode),
+	},
+	{
+		.data_type	= QMI_OPT_FLAG,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u8),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+				option_valid),
+	},
+	{
+		.data_type	= QMI_UNSIGNED_8_BYTE,
+		.elem_len	= 1,
+		.elem_size	= sizeof(u64),
+		.array_type	= NO_ARRAY,
+		.tlv_type	= 0x11,
+		.offset		= offsetof(struct
+				qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+				option),
+	},
+	{
+		.data_type	= QMI_EOTI,
+		.array_type	= NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_mode_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
+				qmi_wlanfw_qdss_trace_mode_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 qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
 	{
 		.data_type	= QMI_OPT_FLAG,
@@ -1510,6 +1698,156 @@ static struct qmi_elem_info qmi_wlanfw_c
 	},
 };
 
+int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab,
+					     const u8 *buffer, unsigned int file_len)
+{
+	int ret = 0;
+	struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 *req;
+	struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 resp;
+	struct qmi_txn txn = {};
+	const u8 *temp = buffer;
+	unsigned int  remaining;
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	memset(&resp, 0, sizeof(resp));
+
+	remaining = file_len;
+	while (remaining) {
+		req->total_size_valid = 1;
+		req->total_size = file_len;
+		req->seg_id_valid = 1;
+		req->data_valid = 1;
+		req->end_valid = 1;
+
+		if (remaining > QMI_WLANFW_MAX_DATA_SIZE_V01) {
+			req->data_len = QMI_WLANFW_MAX_DATA_SIZE_V01;
+		} else {
+			req->data_len = remaining;
+			req->end = 1;
+		}
+		memcpy(req->data, temp, req->data_len);
+
+		ret = qmi_txn_init(&ab->qmi.handle, &txn,
+				   qmi_wlanfw_qdss_trace_config_download_resp_msg_v01_ei,
+				   &resp);
+		if (ret < 0)
+			goto out;
+
+		ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+				       QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01,
+				       QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN,
+				       qmi_wlanfw_qdss_trace_config_download_req_msg_v01_ei, req);
+		if (ret < 0) {
+			ath11k_warn(ab, "Failed to send QDSS config download request,err = %d\n", ret);
+			goto out;
+		}
+
+		ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
+		if (ret < 0)
+			goto out;
+
+		if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+			ath11k_warn(ab, "QDSS config download request failed, result: %d, err: %d\n",
+				    resp.resp.result, resp.resp.error);
+			ret = -EINVAL;
+			goto out;
+		}
+		remaining -= req->data_len;
+		temp += req->data_len;
+		req->seg_id++;
+	}
+
+out:
+	kfree(req);
+	return ret;
+}
+
+int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab,
+				    enum wlfw_qdss_trace_mode_enum_v01 mode)
+{
+	int ret = 0;
+	struct qmi_txn txn = {};
+	struct qmi_wlanfw_qdss_trace_mode_req_msg_v01 req;
+	struct qmi_wlanfw_qdss_trace_mode_resp_msg_v01 resp;
+
+	memset(&req, 0, sizeof(req));
+	memset(&resp, 0, sizeof(resp));
+
+	req.mode_valid = 1;
+	req.mode = mode;
+	req.option_valid = 1;
+	req.option = 0;
+
+	ret = qmi_txn_init(&ab->qmi.handle, &txn,
+			   qmi_wlanfw_qdss_trace_mode_resp_msg_v01_ei, &resp);
+	if (ret < 0)
+		goto out;
+
+	ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+			       QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01,
+			       QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN,
+			       qmi_wlanfw_qdss_trace_mode_req_msg_v01_ei, &req);
+	if (ret < 0) {
+		ath11k_warn(ab, "Failed to send QDSS trace mode request,err = %d\n", ret);
+		goto out;
+	}
+
+	ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
+	if (ret < 0)
+		goto out;
+
+	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+		ath11k_warn(ab, "QDSS trace more request failed, result: %d, err: %d\n",
+			    resp.resp.result, resp.resp.error);
+		ret = -EINVAL;
+		goto out;
+	}
+out:
+	return ret;
+}
+
+static int ath11k_qmi_enable_qdss_trace(struct ath11k_base *ab,
+					enum wlfw_qdss_trace_mode_enum_v01 mode)
+{
+	return ath11k_send_qdss_trace_mode_req(ab, mode);
+}
+
+static int ath11k_qmi_send_qdss_config(struct ath11k_base *ab)
+{
+	struct device *dev = ab->dev;
+	const struct firmware *fw_entry;
+	char filename[ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE];
+	int ret;
+
+	snprintf(filename, sizeof(filename),
+		 "%s/%s/%s", ATH11K_FW_DIR, ab->hw_params.fw.dir, ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME);
+	ret = request_firmware(&fw_entry, filename, dev);
+	if (ret) {
+		/* for backward compatability */
+		snprintf(filename, sizeof(filename),
+			 "%s", ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME);
+		ret = request_firmware(&fw_entry, filename, dev);
+		if (ret) {
+			ath11k_warn(ab, "qmi failed to load QDSS config: %s\n", filename);
+			return ret;
+		}
+	}
+
+	ret = wlfw_send_qdss_trace_config_download_req(ab, fw_entry->data,
+						       fw_entry->size);
+	if (ret < 0) {
+		ath11k_warn(ab, "qmi failed to load QDSS config to FW: %d\n", ret);
+		goto out;
+	}
+out:
+	release_firmware(fw_entry);
+
+	return ret;
+}
+
 static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
 {
 	struct qmi_wlanfw_host_cap_req_msg_v01 req;
@@ -1615,7 +1953,12 @@ static int ath11k_qmi_fw_ind_register_se
 	req->cal_done_enable = 1;
 	req->fw_init_done_enable_valid = 1;
 	req->fw_init_done_enable = 1;
-
+	req->qdss_trace_req_mem_enable_valid = 1;
+	req->qdss_trace_req_mem_enable = 1;
+	req->qdss_trace_save_enable_valid = 1;
+	req->qdss_trace_save_enable = 1;
+	req->qdss_trace_free_enable_valid = 1;
+	req->qdss_trace_free_enable = 1;
 	req->pin_connect_result_enable_valid = 0;
 	req->pin_connect_result_enable = 0;
 
@@ -2382,6 +2725,31 @@ void ath11k_qmi_firmware_stop(struct ath
 	}
 }
 
+int ath11k_config_qdss(struct ath11k_base *ab)
+{
+	int ret;
+
+	/* Disabling qdss trace for FTM as it causes hig evt latency in FW */
+	if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
+		return 0;
+
+	if (enable_qdss_trace) {
+		ret = ath11k_qmi_send_qdss_config(ab);
+		if (ret < 0) {
+			ath11k_warn(ab, "Failed to download QDSS config to FW: %d\n", ret);
+			return ret;
+		}
+		ret = ath11k_qmi_enable_qdss_trace(ab, QMI_WLANFW_QDSS_TRACE_ON_V01);
+		if (ret < 0) {
+			ath11k_warn(ab, "Failed to enable QDSS trace: %d\n", ret);
+			return ret;
+		}
+		ath11k_info(ab, "QDSS configuration is completed\n");
+	}
+
+	return 0;
+}
+
 int ath11k_qmi_firmware_start(struct ath11k_base *ab,
 			      u32 mode)
 {
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -30,6 +30,8 @@
 #define ATH11K_QMI_CALDB_SIZE			0x480000
 #define ATH11K_QMI_BDF_EXT_STR_LENGTH		0x20
 #define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT	3
+#define ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE 64
+#define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin"
 
 #define QMI_WLFW_REQUEST_MEM_IND_V01		0x0035
 #define QMI_WLFW_FW_MEM_READY_IND_V01		0x0037
@@ -138,7 +140,51 @@ struct ath11k_qmi {
 	wait_queue_head_t cold_boot_waitq;
 };
 
-#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN		189
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6167
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044
+
+struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 {
+	u8 total_size_valid;
+	u32 total_size;
+	u8 seg_id_valid;
+	u32 seg_id;
+	u8 data_valid;
+	u32 data_len;
+	u8 data[QMI_WLANFW_MAX_DATA_SIZE_V01];
+	u8 end_valid;
+	u8 end;
+};
+
+struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+
+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01 0x0045
+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18
+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7
+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_V01 0x0045
+
+enum wlfw_qdss_trace_mode_enum_v01 {
+	WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
+	QMI_WLANFW_QDSS_TRACE_OFF_V01 = 0,
+	QMI_WLANFW_QDSS_TRACE_ON_V01 = 1,
+	WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
+struct qmi_wlanfw_qdss_trace_mode_req_msg_v01 {
+	u8 mode_valid;
+	enum wlfw_qdss_trace_mode_enum_v01 mode;
+	u8 option_valid;
+	u64 option;
+};
+
+struct qmi_wlanfw_qdss_trace_mode_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+
+#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN		194
 #define QMI_WLANFW_HOST_CAP_REQ_V01			0x0034
 #define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN	7
 #define QMI_WLFW_HOST_CAP_RESP_V01			0x0034
@@ -177,13 +223,15 @@ struct qmi_wlanfw_host_cap_req_msg_v01 {
 	u32 mem_bucket;
 	u8 mem_cfg_mode_valid;
 	u8 mem_cfg_mode;
+	u8 cal_duration_valid;
+	u16 cal_duration;
 };
 
 struct qmi_wlanfw_host_cap_resp_msg_v01 {
 	struct qmi_response_type_v01 resp;
 };
 
-#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN		54
+#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN		66
 #define QMI_WLANFW_IND_REGISTER_REQ_V01				0x0020
 #define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN		18
 #define QMI_WLANFW_IND_REGISTER_RESP_V01			0x0020
@@ -214,6 +262,12 @@ struct qmi_wlanfw_ind_register_req_msg_v
 	u8 xo_cal_enable;
 	u8 cal_done_enable_valid;
 	u8 cal_done_enable;
+	u8 qdss_trace_req_mem_enable_valid;
+	u8 qdss_trace_req_mem_enable;
+	u8 qdss_trace_save_enable_valid;
+	u8 qdss_trace_save_enable;
+	u8 qdss_trace_free_enable_valid;
+	u8 qdss_trace_free_enable;
 };
 
 struct qmi_wlanfw_ind_register_resp_msg_v01 {
@@ -474,5 +528,11 @@ void ath11k_qmi_event_work(struct work_s
 void ath11k_qmi_msg_recv_work(struct work_struct *work);
 void ath11k_qmi_deinit_service(struct ath11k_base *ab);
 int ath11k_qmi_init_service(struct ath11k_base *ab);
+int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab,
+		const u8 *buffer, unsigned int len);
+
+int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab,
+		enum wlfw_qdss_trace_mode_enum_v01 mode);
+
 
 #endif
