xref: /wlan-dirver/platform/cnss2/qmi.c (revision ae2498e9874c86a1a26ad270494a5ae38711cb14)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5  */
6 
7 #include <linux/module.h>
8 #include <linux/soc/qcom/qmi.h>
9 
10 #include "bus.h"
11 #include "debug.h"
12 #include "main.h"
13 #include "qmi.h"
14 #include "genl.h"
15 
16 #define WLFW_SERVICE_INS_ID_V01		1
17 #define WLFW_CLIENT_ID			0x4b4e454c
18 #define BDF_FILE_NAME_PREFIX		"bdwlan"
19 #define ELF_BDF_FILE_NAME		"bdwlan.elf"
20 #define ELF_BDF_FILE_NAME_GF		"bdwlang.elf"
21 #define ELF_BDF_FILE_NAME_PREFIX	"bdwlan.e"
22 #define ELF_BDF_FILE_NAME_GF_PREFIX	"bdwlang.e"
23 #define BIN_BDF_FILE_NAME		"bdwlan.bin"
24 #define BIN_BDF_FILE_NAME_GF		"bdwlang.bin"
25 #define BIN_BDF_FILE_NAME_PREFIX	"bdwlan.b"
26 #define BIN_BDF_FILE_NAME_GF_PREFIX	"bdwlang.b"
27 #define REGDB_FILE_NAME			"regdb.bin"
28 #define HDS_FILE_NAME			"hds.bin"
29 #define CHIP_ID_GF_MASK			0x10
30 
31 #define CONN_ROAM_FILE_NAME		"wlan-connection-roaming"
32 #define INI_EXT			".ini"
33 #define INI_FILE_NAME_LEN		100
34 
35 #define QDSS_TRACE_CONFIG_FILE		"qdss_trace_config"
36 #ifdef CONFIG_CNSS2_DEBUG
37 #define QDSS_DEBUG_FILE_STR		"debug_"
38 #else
39 #define QDSS_DEBUG_FILE_STR		""
40 #endif
41 #define HW_V1_NUMBER			"v1"
42 #define HW_V2_NUMBER			"v2"
43 
44 #define QMI_WLFW_TIMEOUT_MS		(plat_priv->ctrl_params.qmi_timeout)
45 #define QMI_WLFW_TIMEOUT_JF		msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS)
46 #define COEX_TIMEOUT			QMI_WLFW_TIMEOUT_JF
47 #define IMS_TIMEOUT                     QMI_WLFW_TIMEOUT_JF
48 
49 #define QMI_WLFW_MAX_RECV_BUF_SIZE	SZ_8K
50 #define IMSPRIVATE_SERVICE_MAX_MSG_LEN	SZ_8K
51 #define DMS_QMI_MAX_MSG_LEN		SZ_256
52 #define MAX_SHADOW_REG_RESERVED		2
53 #define MAX_NUM_SHADOW_REG_V3	(QMI_WLFW_MAX_NUM_SHADOW_REG_V3_USAGE_V01 - \
54 				 MAX_SHADOW_REG_RESERVED)
55 
56 #define QMI_WLFW_MAC_READY_TIMEOUT_MS	50
57 #define QMI_WLFW_MAC_READY_MAX_RETRY	200
58 
59 #ifdef CONFIG_CNSS2_DEBUG
60 static bool ignore_qmi_failure;
61 #define CNSS_QMI_ASSERT() CNSS_ASSERT(ignore_qmi_failure)
62 void cnss_ignore_qmi_failure(bool ignore)
63 {
64 	ignore_qmi_failure = ignore;
65 }
66 #else
67 #define CNSS_QMI_ASSERT() do { } while (0)
68 void cnss_ignore_qmi_failure(bool ignore) { }
69 #endif
70 
71 static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode)
72 {
73 	switch (mode) {
74 	case CNSS_MISSION:
75 		return "MISSION";
76 	case CNSS_FTM:
77 		return "FTM";
78 	case CNSS_EPPING:
79 		return "EPPING";
80 	case CNSS_WALTEST:
81 		return "WALTEST";
82 	case CNSS_OFF:
83 		return "OFF";
84 	case CNSS_CCPM:
85 		return "CCPM";
86 	case CNSS_QVIT:
87 		return "QVIT";
88 	case CNSS_CALIBRATION:
89 		return "CALIBRATION";
90 	default:
91 		return "UNKNOWN";
92 	}
93 }
94 
95 static int qmi_send_wait(struct qmi_handle *qmi, void *req, void *rsp,
96 			 struct qmi_elem_info *req_ei,
97 			 struct qmi_elem_info *rsp_ei,
98 			 int req_id, size_t req_len,
99 			 unsigned long timeout)
100 {
101 	struct qmi_txn txn;
102 	int ret;
103 	char *err_msg;
104 	struct qmi_response_type_v01 *resp = rsp;
105 
106 	ret = qmi_txn_init(qmi, &txn, rsp_ei, rsp);
107 	if (ret < 0) {
108 		err_msg = "Qmi fail: fail to init txn,";
109 		goto out;
110 	}
111 
112 	ret = qmi_send_request(qmi, NULL, &txn, req_id,
113 			       req_len, req_ei, req);
114 	if (ret < 0) {
115 		qmi_txn_cancel(&txn);
116 		err_msg = "Qmi fail: fail to send req,";
117 		goto out;
118 	}
119 
120 	ret = qmi_txn_wait(&txn, timeout);
121 	if (ret < 0) {
122 		err_msg = "Qmi fail: wait timeout,";
123 		goto out;
124 	} else if (resp->result != QMI_RESULT_SUCCESS_V01) {
125 		err_msg = "Qmi fail: request rejected,";
126 		cnss_pr_err("Qmi fail: respons with error:%d\n",
127 			    resp->error);
128 		ret = -resp->result;
129 		goto out;
130 	}
131 
132 	cnss_pr_dbg("req %x success\n", req_id);
133 	return 0;
134 out:
135 	cnss_pr_err("%s req %x, ret %d\n", err_msg, req_id, ret);
136 	return ret;
137 }
138 
139 static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv)
140 {
141 	struct wlfw_ind_register_req_msg_v01 *req;
142 	struct wlfw_ind_register_resp_msg_v01 *resp;
143 	struct qmi_txn txn;
144 	int ret = 0;
145 
146 	cnss_pr_dbg("Sending indication register message, state: 0x%lx\n",
147 		    plat_priv->driver_state);
148 
149 	req = kzalloc(sizeof(*req), GFP_KERNEL);
150 	if (!req)
151 		return -ENOMEM;
152 
153 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
154 	if (!resp) {
155 		kfree(req);
156 		return -ENOMEM;
157 	}
158 
159 	req->client_id_valid = 1;
160 	req->client_id = WLFW_CLIENT_ID;
161 	req->request_mem_enable_valid = 1;
162 	req->request_mem_enable = 1;
163 	req->fw_mem_ready_enable_valid = 1;
164 	req->fw_mem_ready_enable = 1;
165 	/* fw_ready indication is replaced by fw_init_done in HST/HSP */
166 	req->fw_init_done_enable_valid = 1;
167 	req->fw_init_done_enable = 1;
168 	req->pin_connect_result_enable_valid = 1;
169 	req->pin_connect_result_enable = 1;
170 	req->cal_done_enable_valid = 1;
171 	req->cal_done_enable = 1;
172 	req->qdss_trace_req_mem_enable_valid = 1;
173 	req->qdss_trace_req_mem_enable = 1;
174 	req->qdss_trace_save_enable_valid = 1;
175 	req->qdss_trace_save_enable = 1;
176 	req->qdss_trace_free_enable_valid = 1;
177 	req->qdss_trace_free_enable = 1;
178 	req->respond_get_info_enable_valid = 1;
179 	req->respond_get_info_enable = 1;
180 	req->wfc_call_twt_config_enable_valid = 1;
181 	req->wfc_call_twt_config_enable = 1;
182 
183 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
184 			   wlfw_ind_register_resp_msg_v01_ei, resp);
185 	if (ret < 0) {
186 		cnss_pr_err("Failed to initialize txn for indication register request, err: %d\n",
187 			    ret);
188 		goto out;
189 	}
190 
191 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
192 			       QMI_WLFW_IND_REGISTER_REQ_V01,
193 			       WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN,
194 			       wlfw_ind_register_req_msg_v01_ei, req);
195 	if (ret < 0) {
196 		qmi_txn_cancel(&txn);
197 		cnss_pr_err("Failed to send indication register request, err: %d\n",
198 			    ret);
199 		goto out;
200 	}
201 
202 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
203 	if (ret < 0) {
204 		cnss_pr_err("Failed to wait for response of indication register request, err: %d\n",
205 			    ret);
206 		goto out;
207 	}
208 
209 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
210 		cnss_pr_err("Indication register request failed, result: %d, err: %d\n",
211 			    resp->resp.result, resp->resp.error);
212 		ret = -resp->resp.result;
213 		goto out;
214 	}
215 
216 	if (resp->fw_status_valid) {
217 		if (resp->fw_status & QMI_WLFW_ALREADY_REGISTERED_V01) {
218 			ret = -EALREADY;
219 			goto qmi_registered;
220 		}
221 	}
222 
223 	kfree(req);
224 	kfree(resp);
225 	return 0;
226 
227 out:
228 	CNSS_QMI_ASSERT();
229 
230 qmi_registered:
231 	kfree(req);
232 	kfree(resp);
233 	return ret;
234 }
235 
236 static void cnss_wlfw_host_cap_parse_mlo(struct cnss_plat_data *plat_priv,
237 					 struct wlfw_host_cap_req_msg_v01 *req)
238 {
239 	if (plat_priv->device_id == KIWI_DEVICE_ID ||
240 	    plat_priv->device_id == MANGO_DEVICE_ID) {
241 		req->mlo_capable_valid = 1;
242 		req->mlo_capable = 1;
243 		req->mlo_chip_id_valid = 1;
244 		req->mlo_chip_id = 0;
245 		req->mlo_group_id_valid = 1;
246 		req->mlo_group_id = 0;
247 		req->max_mlo_peer_valid = 1;
248 		/* Max peer number generally won't change for the same device
249 		 * but needs to be synced with host driver.
250 		 */
251 		req->max_mlo_peer = 32;
252 		req->mlo_num_chips_valid = 1;
253 		req->mlo_num_chips = 1;
254 		req->mlo_chip_info_valid = 1;
255 		req->mlo_chip_info[0].chip_id = 0;
256 		req->mlo_chip_info[0].num_local_links = 2;
257 		req->mlo_chip_info[0].hw_link_id[0] = 0;
258 		req->mlo_chip_info[0].hw_link_id[1] = 1;
259 		req->mlo_chip_info[0].valid_mlo_link_id[0] = 1;
260 		req->mlo_chip_info[0].valid_mlo_link_id[1] = 1;
261 	}
262 }
263 
264 static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv)
265 {
266 	struct wlfw_host_cap_req_msg_v01 *req;
267 	struct wlfw_host_cap_resp_msg_v01 *resp;
268 	struct qmi_txn txn;
269 	int ret = 0;
270 	u64 iova_start = 0, iova_size = 0,
271 	    iova_ipa_start = 0, iova_ipa_size = 0;
272 	u64 feature_list = 0;
273 
274 	cnss_pr_dbg("Sending host capability message, state: 0x%lx\n",
275 		    plat_priv->driver_state);
276 
277 	req = kzalloc(sizeof(*req), GFP_KERNEL);
278 	if (!req)
279 		return -ENOMEM;
280 
281 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
282 	if (!resp) {
283 		kfree(req);
284 		return -ENOMEM;
285 	}
286 
287 	req->num_clients_valid = 1;
288 	req->num_clients = 1;
289 	cnss_pr_dbg("Number of clients is %d\n", req->num_clients);
290 
291 	req->wake_msi = cnss_bus_get_wake_irq(plat_priv);
292 	if (req->wake_msi) {
293 		cnss_pr_dbg("WAKE MSI base data is %d\n", req->wake_msi);
294 		req->wake_msi_valid = 1;
295 	}
296 
297 	req->bdf_support_valid = 1;
298 	req->bdf_support = 1;
299 
300 	req->m3_support_valid = 1;
301 	req->m3_support = 1;
302 
303 	req->m3_cache_support_valid = 1;
304 	req->m3_cache_support = 1;
305 
306 	req->cal_done_valid = 1;
307 	req->cal_done = plat_priv->cal_done;
308 	cnss_pr_dbg("Calibration done is %d\n", plat_priv->cal_done);
309 
310 	if (cnss_bus_is_smmu_s1_enabled(plat_priv) &&
311 	    !cnss_bus_get_iova(plat_priv, &iova_start, &iova_size) &&
312 	    !cnss_bus_get_iova_ipa(plat_priv, &iova_ipa_start,
313 				   &iova_ipa_size)) {
314 		req->ddr_range_valid = 1;
315 		req->ddr_range[0].start = iova_start;
316 		req->ddr_range[0].size = iova_size + iova_ipa_size;
317 		cnss_pr_dbg("Sending iova starting 0x%llx with size 0x%llx\n",
318 			    req->ddr_range[0].start, req->ddr_range[0].size);
319 	}
320 
321 	req->host_build_type_valid = 1;
322 	req->host_build_type = cnss_get_host_build_type();
323 
324 	cnss_wlfw_host_cap_parse_mlo(plat_priv, req);
325 
326 	ret = cnss_get_feature_list(plat_priv, &feature_list);
327 	if (!ret) {
328 		req->feature_list_valid = 1;
329 		req->feature_list = feature_list;
330 		cnss_pr_dbg("Sending feature list 0x%llx\n",
331 			    req->feature_list);
332 	}
333 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
334 			   wlfw_host_cap_resp_msg_v01_ei, resp);
335 	if (ret < 0) {
336 		cnss_pr_err("Failed to initialize txn for host capability request, err: %d\n",
337 			    ret);
338 		goto out;
339 	}
340 
341 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
342 			       QMI_WLFW_HOST_CAP_REQ_V01,
343 			       WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
344 			       wlfw_host_cap_req_msg_v01_ei, req);
345 	if (ret < 0) {
346 		qmi_txn_cancel(&txn);
347 		cnss_pr_err("Failed to send host capability request, err: %d\n",
348 			    ret);
349 		goto out;
350 	}
351 
352 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
353 	if (ret < 0) {
354 		cnss_pr_err("Failed to wait for response of host capability request, err: %d\n",
355 			    ret);
356 		goto out;
357 	}
358 
359 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
360 		cnss_pr_err("Host capability request failed, result: %d, err: %d\n",
361 			    resp->resp.result, resp->resp.error);
362 		ret = -resp->resp.result;
363 		goto out;
364 	}
365 
366 	kfree(req);
367 	kfree(resp);
368 	return 0;
369 
370 out:
371 	CNSS_QMI_ASSERT();
372 	kfree(req);
373 	kfree(resp);
374 	return ret;
375 }
376 
377 int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
378 {
379 	struct wlfw_respond_mem_req_msg_v01 *req;
380 	struct wlfw_respond_mem_resp_msg_v01 *resp;
381 	struct qmi_txn txn;
382 	struct cnss_fw_mem *fw_mem = plat_priv->fw_mem;
383 	int ret = 0, i;
384 
385 	cnss_pr_dbg("Sending respond memory message, state: 0x%lx\n",
386 		    plat_priv->driver_state);
387 
388 	req = kzalloc(sizeof(*req), GFP_KERNEL);
389 	if (!req)
390 		return -ENOMEM;
391 
392 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
393 	if (!resp) {
394 		kfree(req);
395 		return -ENOMEM;
396 	}
397 
398 	if (plat_priv->fw_mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) {
399 		cnss_pr_err("Invalid seg len %u\n", plat_priv->fw_mem_seg_len);
400 		ret = -EINVAL;
401 		goto out;
402 	}
403 
404 	req->mem_seg_len = plat_priv->fw_mem_seg_len;
405 	for (i = 0; i < req->mem_seg_len; i++) {
406 		if (!fw_mem[i].pa || !fw_mem[i].size) {
407 			if (fw_mem[i].type == 0) {
408 				cnss_pr_err("Invalid memory for FW type, segment = %d\n",
409 					    i);
410 				ret = -EINVAL;
411 				goto out;
412 			}
413 			cnss_pr_err("Memory for FW is not available for type: %u\n",
414 				    fw_mem[i].type);
415 			ret = -ENOMEM;
416 			goto out;
417 		}
418 
419 		cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
420 			    fw_mem[i].va, &fw_mem[i].pa,
421 			    fw_mem[i].size, fw_mem[i].type);
422 
423 		req->mem_seg[i].addr = fw_mem[i].pa;
424 		req->mem_seg[i].size = fw_mem[i].size;
425 		req->mem_seg[i].type = fw_mem[i].type;
426 	}
427 
428 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
429 			   wlfw_respond_mem_resp_msg_v01_ei, resp);
430 	if (ret < 0) {
431 		cnss_pr_err("Failed to initialize txn for respond memory request, err: %d\n",
432 			    ret);
433 		goto out;
434 	}
435 
436 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
437 			       QMI_WLFW_RESPOND_MEM_REQ_V01,
438 			       WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN,
439 			       wlfw_respond_mem_req_msg_v01_ei, req);
440 	if (ret < 0) {
441 		qmi_txn_cancel(&txn);
442 		cnss_pr_err("Failed to send respond memory request, err: %d\n",
443 			    ret);
444 		goto out;
445 	}
446 
447 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
448 	if (ret < 0) {
449 		cnss_pr_err("Failed to wait for response of respond memory request, err: %d\n",
450 			    ret);
451 		goto out;
452 	}
453 
454 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
455 		cnss_pr_err("Respond memory request failed, result: %d, err: %d\n",
456 			    resp->resp.result, resp->resp.error);
457 		ret = -resp->resp.result;
458 		goto out;
459 	}
460 
461 	kfree(req);
462 	kfree(resp);
463 	return 0;
464 
465 out:
466 	CNSS_QMI_ASSERT();
467 	kfree(req);
468 	kfree(resp);
469 	return ret;
470 }
471 
472 int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
473 {
474 	struct wlfw_cap_req_msg_v01 *req;
475 	struct wlfw_cap_resp_msg_v01 *resp;
476 	struct qmi_txn txn;
477 	char *fw_build_timestamp;
478 	int ret = 0, i;
479 
480 	cnss_pr_dbg("Sending target capability message, state: 0x%lx\n",
481 		    plat_priv->driver_state);
482 
483 	req = kzalloc(sizeof(*req), GFP_KERNEL);
484 	if (!req)
485 		return -ENOMEM;
486 
487 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
488 	if (!resp) {
489 		kfree(req);
490 		return -ENOMEM;
491 	}
492 
493 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
494 			   wlfw_cap_resp_msg_v01_ei, resp);
495 	if (ret < 0) {
496 		cnss_pr_err("Failed to initialize txn for target capability request, err: %d\n",
497 			    ret);
498 		goto out;
499 	}
500 
501 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
502 			       QMI_WLFW_CAP_REQ_V01,
503 			       WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN,
504 			       wlfw_cap_req_msg_v01_ei, req);
505 	if (ret < 0) {
506 		qmi_txn_cancel(&txn);
507 		cnss_pr_err("Failed to send respond target capability request, err: %d\n",
508 			    ret);
509 		goto out;
510 	}
511 
512 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
513 	if (ret < 0) {
514 		cnss_pr_err("Failed to wait for response of target capability request, err: %d\n",
515 			    ret);
516 		goto out;
517 	}
518 
519 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
520 		cnss_pr_err("Target capability request failed, result: %d, err: %d\n",
521 			    resp->resp.result, resp->resp.error);
522 		ret = -resp->resp.result;
523 		goto out;
524 	}
525 
526 	if (resp->chip_info_valid) {
527 		plat_priv->chip_info.chip_id = resp->chip_info.chip_id;
528 		plat_priv->chip_info.chip_family = resp->chip_info.chip_family;
529 	}
530 	if (resp->board_info_valid)
531 		plat_priv->board_info.board_id = resp->board_info.board_id;
532 	else
533 		plat_priv->board_info.board_id = 0xFF;
534 	if (resp->soc_info_valid)
535 		plat_priv->soc_info.soc_id = resp->soc_info.soc_id;
536 	if (resp->fw_version_info_valid) {
537 		plat_priv->fw_version_info.fw_version =
538 			resp->fw_version_info.fw_version;
539 		fw_build_timestamp = resp->fw_version_info.fw_build_timestamp;
540 		fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN] = '\0';
541 		strlcpy(plat_priv->fw_version_info.fw_build_timestamp,
542 			resp->fw_version_info.fw_build_timestamp,
543 			QMI_WLFW_MAX_TIMESTAMP_LEN + 1);
544 	}
545 	if (resp->fw_build_id_valid) {
546 		resp->fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN] = '\0';
547 		strlcpy(plat_priv->fw_build_id, resp->fw_build_id,
548 			QMI_WLFW_MAX_BUILD_ID_LEN + 1);
549 	}
550 	/* FW will send aop retention volatage for qca6490 */
551 	if (resp->voltage_mv_valid) {
552 		plat_priv->cpr_info.voltage = resp->voltage_mv;
553 		cnss_pr_dbg("Voltage for CPR: %dmV\n",
554 			    plat_priv->cpr_info.voltage);
555 		cnss_update_cpr_info(plat_priv);
556 	}
557 	if (resp->time_freq_hz_valid) {
558 		plat_priv->device_freq_hz = resp->time_freq_hz;
559 		cnss_pr_dbg("Device frequency is %d HZ\n",
560 			    plat_priv->device_freq_hz);
561 	}
562 	if (resp->otp_version_valid)
563 		plat_priv->otp_version = resp->otp_version;
564 	if (resp->dev_mem_info_valid) {
565 		for (i = 0; i < QMI_WLFW_MAX_DEV_MEM_NUM_V01; i++) {
566 			plat_priv->dev_mem_info[i].start =
567 				resp->dev_mem_info[i].start;
568 			plat_priv->dev_mem_info[i].size =
569 				resp->dev_mem_info[i].size;
570 			cnss_pr_buf("Device memory info[%d]: start = 0x%llx, size = 0x%llx\n",
571 				    i, plat_priv->dev_mem_info[i].start,
572 				    plat_priv->dev_mem_info[i].size);
573 		}
574 	}
575 	if (resp->fw_caps_valid) {
576 		plat_priv->fw_pcie_gen_switch =
577 			!!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01);
578 		plat_priv->fw_caps = resp->fw_caps;
579 	}
580 
581 	if (resp->hang_data_length_valid &&
582 	    resp->hang_data_length &&
583 	    resp->hang_data_length <= WLFW_MAX_HANG_EVENT_DATA_SIZE)
584 		plat_priv->hang_event_data_len = resp->hang_data_length;
585 	else
586 		plat_priv->hang_event_data_len = 0;
587 
588 	if (resp->hang_data_addr_offset_valid)
589 		plat_priv->hang_data_addr_offset = resp->hang_data_addr_offset;
590 	else
591 		plat_priv->hang_data_addr_offset = 0;
592 
593 	if (resp->hwid_bitmap_valid)
594 		plat_priv->hwid_bitmap = resp->hwid_bitmap;
595 
596 	if (resp->ol_cpr_cfg_valid)
597 		cnss_aop_ol_cpr_cfg_setup(plat_priv, &resp->ol_cpr_cfg);
598 
599 	cnss_pr_dbg("Target capability: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, otp_version: 0x%x\n",
600 		    plat_priv->chip_info.chip_id,
601 		    plat_priv->chip_info.chip_family,
602 		    plat_priv->board_info.board_id, plat_priv->soc_info.soc_id,
603 		    plat_priv->otp_version);
604 	cnss_pr_dbg("fw_version: 0x%x, fw_build_timestamp: %s, fw_build_id: %s, hwid_bitmap:0x%x\n",
605 		    plat_priv->fw_version_info.fw_version,
606 		    plat_priv->fw_version_info.fw_build_timestamp,
607 		    plat_priv->fw_build_id,
608 		    plat_priv->hwid_bitmap);
609 	cnss_pr_dbg("Hang event params, Length: 0x%x, Offset Address: 0x%x\n",
610 		    plat_priv->hang_event_data_len,
611 		    plat_priv->hang_data_addr_offset);
612 
613 	kfree(req);
614 	kfree(resp);
615 	return 0;
616 
617 out:
618 	CNSS_QMI_ASSERT();
619 	kfree(req);
620 	kfree(resp);
621 	return ret;
622 }
623 
624 static int cnss_get_bdf_file_name(struct cnss_plat_data *plat_priv,
625 				  u32 bdf_type, char *filename,
626 				  u32 filename_len)
627 {
628 	char filename_tmp[MAX_FIRMWARE_NAME_LEN];
629 	int ret = 0;
630 
631 	switch (bdf_type) {
632 	case CNSS_BDF_ELF:
633 		/* Board ID will be equal or less than 0xFF in GF mask case */
634 		if (plat_priv->board_info.board_id == 0xFF) {
635 			if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK)
636 				snprintf(filename_tmp, filename_len,
637 					 ELF_BDF_FILE_NAME_GF);
638 			else
639 				snprintf(filename_tmp, filename_len,
640 					 ELF_BDF_FILE_NAME);
641 		} else if (plat_priv->board_info.board_id < 0xFF) {
642 			if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK)
643 				snprintf(filename_tmp, filename_len,
644 					 ELF_BDF_FILE_NAME_GF_PREFIX "%02x",
645 					 plat_priv->board_info.board_id);
646 			else
647 				snprintf(filename_tmp, filename_len,
648 					 ELF_BDF_FILE_NAME_PREFIX "%02x",
649 					 plat_priv->board_info.board_id);
650 		} else {
651 			snprintf(filename_tmp, filename_len,
652 				 BDF_FILE_NAME_PREFIX "%02x.e%02x",
653 				 plat_priv->board_info.board_id >> 8 & 0xFF,
654 				 plat_priv->board_info.board_id & 0xFF);
655 		}
656 		break;
657 	case CNSS_BDF_BIN:
658 		if (plat_priv->board_info.board_id == 0xFF) {
659 			if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK)
660 				snprintf(filename_tmp, filename_len,
661 					 BIN_BDF_FILE_NAME_GF);
662 			else
663 				snprintf(filename_tmp, filename_len,
664 					 BIN_BDF_FILE_NAME);
665 		} else if (plat_priv->board_info.board_id < 0xFF) {
666 			if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK)
667 				snprintf(filename_tmp, filename_len,
668 					 BIN_BDF_FILE_NAME_GF_PREFIX "%02x",
669 					 plat_priv->board_info.board_id);
670 			else
671 				snprintf(filename_tmp, filename_len,
672 					 BIN_BDF_FILE_NAME_PREFIX "%02x",
673 					 plat_priv->board_info.board_id);
674 		} else {
675 			snprintf(filename_tmp, filename_len,
676 				 BDF_FILE_NAME_PREFIX "%02x.b%02x",
677 				 plat_priv->board_info.board_id >> 8 & 0xFF,
678 				 plat_priv->board_info.board_id & 0xFF);
679 		}
680 		break;
681 	case CNSS_BDF_REGDB:
682 		snprintf(filename_tmp, filename_len, REGDB_FILE_NAME);
683 		break;
684 	case CNSS_BDF_HDS:
685 		snprintf(filename_tmp, filename_len, HDS_FILE_NAME);
686 		break;
687 	default:
688 		cnss_pr_err("Invalid BDF type: %d\n",
689 			    plat_priv->ctrl_params.bdf_type);
690 		ret = -EINVAL;
691 		break;
692 	}
693 
694 	if (!ret)
695 		cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp);
696 
697 	return ret;
698 }
699 
700 int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
701 				 enum wlfw_ini_file_type_v01 file_type)
702 {
703 	struct wlfw_ini_file_download_req_msg_v01 *req;
704 	struct wlfw_ini_file_download_resp_msg_v01 *resp;
705 	struct qmi_txn txn;
706 	int ret = 0;
707 	const struct firmware *fw;
708 	char filename[INI_FILE_NAME_LEN] = {0};
709 	char tmp_filename[INI_FILE_NAME_LEN] = {0};
710 	const u8 *temp;
711 	unsigned int remaining;
712 	bool backup_supported = false;
713 
714 	cnss_pr_info("INI File %u download\n", file_type);
715 
716 	req = kzalloc(sizeof(*req), GFP_KERNEL);
717 	if (!req)
718 		return -ENOMEM;
719 
720 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
721 	if (!resp) {
722 		kfree(req);
723 		return -ENOMEM;
724 	}
725 
726 	switch (file_type) {
727 	case WLFW_CONN_ROAM_INI_V01:
728 		snprintf(tmp_filename, sizeof(tmp_filename),
729 			 CONN_ROAM_FILE_NAME);
730 		backup_supported = true;
731 		break;
732 	default:
733 		cnss_pr_err("Invalid file type: %u\n", file_type);
734 		ret = -EINVAL;
735 		goto err_req_fw;
736 	}
737 
738 	snprintf(filename, sizeof(filename), "%s%s", tmp_filename, INI_EXT);
739 	/* Fetch the file */
740 	ret = firmware_request_nowarn(&fw, filename, &plat_priv->plat_dev->dev);
741 	if (ret) {
742 		cnss_pr_err("Failed to get INI file %s (%d), Backup file: %s",
743 			    filename, ret,
744 			    backup_supported ? "Supported" : "Not Supported");
745 
746 		if (!backup_supported)
747 			goto err_req_fw;
748 
749 		snprintf(filename, sizeof(filename),
750 			 "%s-%s%s", tmp_filename, "backup", INI_EXT);
751 
752 		ret = firmware_request_nowarn(&fw, filename,
753 					      &plat_priv->plat_dev->dev);
754 		if (ret) {
755 			cnss_pr_err("Failed to get INI file %s (%d)", filename,
756 				    ret);
757 			goto err_req_fw;
758 		}
759 	}
760 
761 	temp = fw->data;
762 	remaining = fw->size;
763 
764 	cnss_pr_dbg("Downloading INI file: %s, size: %u\n", filename,
765 		    remaining);
766 
767 	while (remaining) {
768 		req->file_type_valid = 1;
769 		req->file_type = file_type;
770 		req->total_size_valid = 1;
771 		req->total_size = remaining;
772 		req->seg_id_valid = 1;
773 		req->data_valid = 1;
774 		req->end_valid = 1;
775 
776 		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
777 			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
778 		} else {
779 			req->data_len = remaining;
780 			req->end = 1;
781 		}
782 
783 		memcpy(req->data, temp, req->data_len);
784 
785 		ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
786 				   wlfw_ini_file_download_resp_msg_v01_ei,
787 				   resp);
788 		if (ret < 0) {
789 			cnss_pr_err("Failed to initialize txn for INI file download request, err: %d\n",
790 				    ret);
791 			goto err;
792 		}
793 
794 		ret = qmi_send_request
795 			(&plat_priv->qmi_wlfw, NULL, &txn,
796 			 QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01,
797 			 WLFW_INI_FILE_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
798 			 wlfw_ini_file_download_req_msg_v01_ei, req);
799 		if (ret < 0) {
800 			qmi_txn_cancel(&txn);
801 			cnss_pr_err("Failed to send INI File download request, err: %d\n",
802 				    ret);
803 			goto err;
804 		}
805 
806 		ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
807 		if (ret < 0) {
808 			cnss_pr_err("Failed to wait for response of INI File download request, err: %d\n",
809 				    ret);
810 			goto err;
811 		}
812 
813 		if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
814 			cnss_pr_err("INI file download request failed, result: %d, err: %d\n",
815 				    resp->resp.result, resp->resp.error);
816 			ret = -resp->resp.result;
817 			goto err;
818 		}
819 
820 		remaining -= req->data_len;
821 		temp += req->data_len;
822 		req->seg_id++;
823 	}
824 
825 	release_firmware(fw);
826 
827 	kfree(req);
828 	kfree(resp);
829 	return 0;
830 
831 err:
832 	release_firmware(fw);
833 err_req_fw:
834 	kfree(req);
835 	kfree(resp);
836 
837 	return ret;
838 }
839 
840 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv,
841 				 u32 bdf_type)
842 {
843 	struct wlfw_bdf_download_req_msg_v01 *req;
844 	struct wlfw_bdf_download_resp_msg_v01 *resp;
845 	struct qmi_txn txn;
846 	char filename[MAX_FIRMWARE_NAME_LEN];
847 	const struct firmware *fw_entry = NULL;
848 	const u8 *temp;
849 	unsigned int remaining;
850 	int ret = 0;
851 
852 	cnss_pr_dbg("Sending BDF download message, state: 0x%lx, type: %d\n",
853 		    plat_priv->driver_state, bdf_type);
854 
855 	req = kzalloc(sizeof(*req), GFP_KERNEL);
856 	if (!req)
857 		return -ENOMEM;
858 
859 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
860 	if (!resp) {
861 		kfree(req);
862 		return -ENOMEM;
863 	}
864 
865 	ret = cnss_get_bdf_file_name(plat_priv, bdf_type,
866 				     filename, sizeof(filename));
867 	if (ret)
868 		goto err_req_fw;
869 
870 	if (bdf_type == CNSS_BDF_REGDB)
871 		ret = cnss_request_firmware_direct(plat_priv, &fw_entry,
872 						   filename);
873 	else
874 		ret = firmware_request_nowarn(&fw_entry, filename,
875 					      &plat_priv->plat_dev->dev);
876 
877 	if (ret) {
878 		cnss_pr_err("Failed to load BDF: %s, ret: %d\n", filename, ret);
879 		goto err_req_fw;
880 	}
881 
882 	temp = fw_entry->data;
883 	remaining = fw_entry->size;
884 
885 	cnss_pr_dbg("Downloading BDF: %s, size: %u\n", filename, remaining);
886 
887 	while (remaining) {
888 		req->valid = 1;
889 		req->file_id_valid = 1;
890 		req->file_id = plat_priv->board_info.board_id;
891 		req->total_size_valid = 1;
892 		req->total_size = remaining;
893 		req->seg_id_valid = 1;
894 		req->data_valid = 1;
895 		req->end_valid = 1;
896 		req->bdf_type_valid = 1;
897 		req->bdf_type = bdf_type;
898 
899 		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
900 			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
901 		} else {
902 			req->data_len = remaining;
903 			req->end = 1;
904 		}
905 
906 		memcpy(req->data, temp, req->data_len);
907 
908 		ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
909 				   wlfw_bdf_download_resp_msg_v01_ei, resp);
910 		if (ret < 0) {
911 			cnss_pr_err("Failed to initialize txn for BDF download request, err: %d\n",
912 				    ret);
913 			goto err_send;
914 		}
915 
916 		ret = qmi_send_request
917 			(&plat_priv->qmi_wlfw, NULL, &txn,
918 			 QMI_WLFW_BDF_DOWNLOAD_REQ_V01,
919 			 WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
920 			 wlfw_bdf_download_req_msg_v01_ei, req);
921 		if (ret < 0) {
922 			qmi_txn_cancel(&txn);
923 			cnss_pr_err("Failed to send respond BDF download request, err: %d\n",
924 				    ret);
925 			goto err_send;
926 		}
927 
928 		ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
929 		if (ret < 0) {
930 			cnss_pr_err("Failed to wait for response of BDF download request, err: %d\n",
931 				    ret);
932 			goto err_send;
933 		}
934 
935 		if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
936 			cnss_pr_err("BDF download request failed, result: %d, err: %d\n",
937 				    resp->resp.result, resp->resp.error);
938 			ret = -resp->resp.result;
939 			goto err_send;
940 		}
941 
942 		remaining -= req->data_len;
943 		temp += req->data_len;
944 		req->seg_id++;
945 	}
946 
947 	release_firmware(fw_entry);
948 
949 	if (resp->host_bdf_data_valid) {
950 		/* QCA6490 enable S3E regulator for IPA configuration only */
951 		if (!(resp->host_bdf_data & QMI_WLFW_HW_XPA_V01))
952 			cnss_enable_int_pow_amp_vreg(plat_priv);
953 
954 		plat_priv->cbc_file_download =
955 			resp->host_bdf_data & QMI_WLFW_CBC_FILE_DOWNLOAD_V01;
956 		cnss_pr_info("Host BDF config: HW_XPA: %d CalDB: %d\n",
957 			     resp->host_bdf_data & QMI_WLFW_HW_XPA_V01,
958 			     plat_priv->cbc_file_download);
959 	}
960 	kfree(req);
961 	kfree(resp);
962 	return 0;
963 
964 err_send:
965 	release_firmware(fw_entry);
966 err_req_fw:
967 	if (!(bdf_type == CNSS_BDF_REGDB ||
968 	      test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state) ||
969 	      ret == -EAGAIN))
970 		CNSS_QMI_ASSERT();
971 	kfree(req);
972 	kfree(resp);
973 	return ret;
974 }
975 
976 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
977 {
978 	struct wlfw_m3_info_req_msg_v01 *req;
979 	struct wlfw_m3_info_resp_msg_v01 *resp;
980 	struct qmi_txn txn;
981 	struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem;
982 	int ret = 0;
983 
984 	cnss_pr_dbg("Sending M3 information message, state: 0x%lx\n",
985 		    plat_priv->driver_state);
986 
987 	req = kzalloc(sizeof(*req), GFP_KERNEL);
988 	if (!req)
989 		return -ENOMEM;
990 
991 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
992 	if (!resp) {
993 		kfree(req);
994 		return -ENOMEM;
995 	}
996 
997 	if (!m3_mem->pa || !m3_mem->size) {
998 		cnss_pr_err("Memory for M3 is not available\n");
999 		ret = -ENOMEM;
1000 		goto out;
1001 	}
1002 
1003 	cnss_pr_dbg("M3 memory, va: 0x%pK, pa: %pa, size: 0x%zx\n",
1004 		    m3_mem->va, &m3_mem->pa, m3_mem->size);
1005 
1006 	req->addr = plat_priv->m3_mem.pa;
1007 	req->size = plat_priv->m3_mem.size;
1008 
1009 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1010 			   wlfw_m3_info_resp_msg_v01_ei, resp);
1011 	if (ret < 0) {
1012 		cnss_pr_err("Failed to initialize txn for M3 information request, err: %d\n",
1013 			    ret);
1014 		goto out;
1015 	}
1016 
1017 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1018 			       QMI_WLFW_M3_INFO_REQ_V01,
1019 			       WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN,
1020 			       wlfw_m3_info_req_msg_v01_ei, req);
1021 	if (ret < 0) {
1022 		qmi_txn_cancel(&txn);
1023 		cnss_pr_err("Failed to send M3 information request, err: %d\n",
1024 			    ret);
1025 		goto out;
1026 	}
1027 
1028 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1029 	if (ret < 0) {
1030 		cnss_pr_err("Failed to wait for response of M3 information request, err: %d\n",
1031 			    ret);
1032 		goto out;
1033 	}
1034 
1035 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1036 		cnss_pr_err("M3 information request failed, result: %d, err: %d\n",
1037 			    resp->resp.result, resp->resp.error);
1038 		ret = -resp->resp.result;
1039 		goto out;
1040 	}
1041 
1042 	kfree(req);
1043 	kfree(resp);
1044 	return 0;
1045 
1046 out:
1047 	CNSS_QMI_ASSERT();
1048 	kfree(req);
1049 	kfree(resp);
1050 	return ret;
1051 }
1052 
1053 int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv,
1054 				     u8 *mac, u32 mac_len)
1055 {
1056 	struct wlfw_mac_addr_req_msg_v01 req;
1057 	struct wlfw_mac_addr_resp_msg_v01 resp = {0};
1058 	struct qmi_txn txn;
1059 	int ret;
1060 
1061 	if (!plat_priv || !mac || mac_len != QMI_WLFW_MAC_ADDR_SIZE_V01)
1062 		return -EINVAL;
1063 
1064 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1065 			   wlfw_mac_addr_resp_msg_v01_ei, &resp);
1066 	if (ret < 0) {
1067 		cnss_pr_err("Failed to initialize txn for mac req, err: %d\n",
1068 			    ret);
1069 		ret = -EIO;
1070 		goto out;
1071 	}
1072 
1073 		cnss_pr_dbg("Sending WLAN mac req [%pM], state: 0x%lx\n",
1074 			    mac, plat_priv->driver_state);
1075 	memcpy(req.mac_addr, mac, mac_len);
1076 	req.mac_addr_valid = 1;
1077 
1078 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1079 			       QMI_WLFW_MAC_ADDR_REQ_V01,
1080 			       WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN,
1081 			       wlfw_mac_addr_req_msg_v01_ei, &req);
1082 	if (ret < 0) {
1083 		qmi_txn_cancel(&txn);
1084 		cnss_pr_err("Failed to send mac req, err: %d\n", ret);
1085 		ret = -EIO;
1086 		goto out;
1087 	}
1088 
1089 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1090 	if (ret < 0) {
1091 		cnss_pr_err("Failed to wait for resp of mac req, err: %d\n",
1092 			    ret);
1093 		ret = -EIO;
1094 		goto out;
1095 	}
1096 
1097 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
1098 		cnss_pr_err("WLAN mac req failed, result: %d, err: %d\n",
1099 			    resp.resp.result);
1100 		ret = -resp.resp.result;
1101 	}
1102 out:
1103 	return ret;
1104 }
1105 
1106 int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name,
1107 				  u32 total_size)
1108 {
1109 	int ret = 0;
1110 	struct wlfw_qdss_trace_data_req_msg_v01 *req;
1111 	struct wlfw_qdss_trace_data_resp_msg_v01 *resp;
1112 	unsigned char *p_qdss_trace_data_temp, *p_qdss_trace_data = NULL;
1113 	unsigned int remaining;
1114 	struct qmi_txn txn;
1115 
1116 	cnss_pr_dbg("%s\n", __func__);
1117 
1118 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1119 	if (!req)
1120 		return -ENOMEM;
1121 
1122 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1123 	if (!resp) {
1124 		kfree(req);
1125 		return -ENOMEM;
1126 	}
1127 
1128 	p_qdss_trace_data = kzalloc(total_size, GFP_KERNEL);
1129 	if (!p_qdss_trace_data) {
1130 		ret = ENOMEM;
1131 		goto end;
1132 	}
1133 
1134 	remaining = total_size;
1135 	p_qdss_trace_data_temp = p_qdss_trace_data;
1136 	while (remaining && resp->end == 0) {
1137 		ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1138 				   wlfw_qdss_trace_data_resp_msg_v01_ei, resp);
1139 
1140 		if (ret < 0) {
1141 			cnss_pr_err("Fail to init txn for QDSS trace resp %d\n",
1142 				    ret);
1143 			goto fail;
1144 		}
1145 
1146 		ret = qmi_send_request
1147 			(&plat_priv->qmi_wlfw, NULL, &txn,
1148 			 QMI_WLFW_QDSS_TRACE_DATA_REQ_V01,
1149 			 WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN,
1150 			 wlfw_qdss_trace_data_req_msg_v01_ei, req);
1151 
1152 		if (ret < 0) {
1153 			qmi_txn_cancel(&txn);
1154 			cnss_pr_err("Fail to send QDSS trace data req %d\n",
1155 				    ret);
1156 			goto fail;
1157 		}
1158 
1159 		ret = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout);
1160 
1161 		if (ret < 0) {
1162 			cnss_pr_err("QDSS trace resp wait failed with rc %d\n",
1163 				    ret);
1164 			goto fail;
1165 		} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1166 			cnss_pr_err("QMI QDSS trace request rejected, result:%d error:%d\n",
1167 				    resp->resp.result, resp->resp.error);
1168 			ret = -resp->resp.result;
1169 			goto fail;
1170 		} else {
1171 			ret = 0;
1172 		}
1173 
1174 		cnss_pr_dbg("%s: response total size  %d data len %d",
1175 			    __func__, resp->total_size, resp->data_len);
1176 
1177 		if ((resp->total_size_valid == 1 &&
1178 		     resp->total_size == total_size) &&
1179 		   (resp->seg_id_valid == 1 && resp->seg_id == req->seg_id) &&
1180 		   (resp->data_valid == 1 &&
1181 		    resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01) &&
1182 		   resp->data_len <= remaining) {
1183 			memcpy(p_qdss_trace_data_temp,
1184 			       resp->data, resp->data_len);
1185 		} else {
1186 			cnss_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",
1187 				    __func__,
1188 				     total_size, req->seg_id,
1189 				     resp->total_size_valid,
1190 				     resp->total_size,
1191 				     resp->seg_id_valid,
1192 				     resp->seg_id,
1193 				     resp->data_valid,
1194 				     resp->data_len);
1195 			ret = -1;
1196 			goto fail;
1197 		}
1198 
1199 		remaining -= resp->data_len;
1200 		p_qdss_trace_data_temp += resp->data_len;
1201 		req->seg_id++;
1202 	}
1203 
1204 	if (remaining == 0 && (resp->end_valid && resp->end)) {
1205 		ret = cnss_genl_send_msg(p_qdss_trace_data,
1206 					 CNSS_GENL_MSG_TYPE_QDSS, file_name,
1207 					 total_size);
1208 		if (ret < 0) {
1209 			cnss_pr_err("Fail to save QDSS trace data: %d\n",
1210 				    ret);
1211 		ret = -1;
1212 		goto fail;
1213 		}
1214 	} else {
1215 		cnss_pr_err("%s: QDSS trace file corrupted: remaining %u, end_valid %u, end %u",
1216 			    __func__,
1217 			     remaining, resp->end_valid, resp->end);
1218 		ret = -1;
1219 		goto fail;
1220 	}
1221 
1222 fail:
1223 	kfree(p_qdss_trace_data);
1224 
1225 end:
1226 	kfree(req);
1227 	kfree(resp);
1228 	return ret;
1229 }
1230 
1231 void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv,
1232 				char *filename, u32 filename_len)
1233 {
1234 	char filename_tmp[MAX_FIRMWARE_NAME_LEN];
1235 	char *debug_str = QDSS_DEBUG_FILE_STR;
1236 
1237 	if (plat_priv->device_id == KIWI_DEVICE_ID ||
1238 	    plat_priv->device_id == MANGO_DEVICE_ID)
1239 		debug_str = "";
1240 
1241 	if (plat_priv->device_version.major_version == FW_V2_NUMBER)
1242 		snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE
1243 			 "_%s%s.cfg", debug_str, HW_V2_NUMBER);
1244 	else
1245 		snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE
1246 			 "_%s%s.cfg", debug_str, HW_V1_NUMBER);
1247 
1248 	cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp);
1249 }
1250 
1251 int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv)
1252 {
1253 	struct wlfw_qdss_trace_config_download_req_msg_v01 *req;
1254 	struct wlfw_qdss_trace_config_download_resp_msg_v01 *resp;
1255 	struct qmi_txn txn;
1256 	const struct firmware *fw_entry = NULL;
1257 	const u8 *temp;
1258 	char qdss_cfg_filename[MAX_FIRMWARE_NAME_LEN];
1259 	unsigned int remaining;
1260 	int ret = 0;
1261 
1262 	cnss_pr_dbg("Sending QDSS config download message, state: 0x%lx\n",
1263 		    plat_priv->driver_state);
1264 
1265 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1266 	if (!req)
1267 		return -ENOMEM;
1268 
1269 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1270 	if (!resp) {
1271 		kfree(req);
1272 		return -ENOMEM;
1273 	}
1274 
1275 	cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename, sizeof(qdss_cfg_filename));
1276 	ret = cnss_request_firmware_direct(plat_priv, &fw_entry,
1277 					   qdss_cfg_filename);
1278 	if (ret) {
1279 		cnss_pr_dbg("Unable to load %s\n",
1280 			    qdss_cfg_filename);
1281 		goto err_req_fw;
1282 	}
1283 
1284 	temp = fw_entry->data;
1285 	remaining = fw_entry->size;
1286 
1287 	cnss_pr_dbg("Downloading QDSS: %s, size: %u\n",
1288 		    qdss_cfg_filename, remaining);
1289 
1290 	while (remaining) {
1291 		req->total_size_valid = 1;
1292 		req->total_size = remaining;
1293 		req->seg_id_valid = 1;
1294 		req->data_valid = 1;
1295 		req->end_valid = 1;
1296 
1297 		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
1298 			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
1299 		} else {
1300 			req->data_len = remaining;
1301 			req->end = 1;
1302 		}
1303 
1304 		memcpy(req->data, temp, req->data_len);
1305 
1306 		ret = qmi_txn_init
1307 			(&plat_priv->qmi_wlfw, &txn,
1308 			 wlfw_qdss_trace_config_download_resp_msg_v01_ei,
1309 			 resp);
1310 		if (ret < 0) {
1311 			cnss_pr_err("Failed to initialize txn for QDSS download request, err: %d\n",
1312 				    ret);
1313 			goto err_send;
1314 		}
1315 
1316 		ret = qmi_send_request
1317 		      (&plat_priv->qmi_wlfw, NULL, &txn,
1318 		       QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01,
1319 		       WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
1320 		       wlfw_qdss_trace_config_download_req_msg_v01_ei, req);
1321 		if (ret < 0) {
1322 			qmi_txn_cancel(&txn);
1323 			cnss_pr_err("Failed to send respond QDSS download request, err: %d\n",
1324 				    ret);
1325 			goto err_send;
1326 		}
1327 
1328 		ret = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout);
1329 		if (ret < 0) {
1330 			cnss_pr_err("Failed to wait for response of QDSS download request, err: %d\n",
1331 				    ret);
1332 			goto err_send;
1333 		}
1334 
1335 		if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1336 			cnss_pr_err("QDSS download request failed, result: %d, err: %d\n",
1337 				    resp->resp.result, resp->resp.error);
1338 			ret = -resp->resp.result;
1339 			goto err_send;
1340 		}
1341 
1342 		remaining -= req->data_len;
1343 		temp += req->data_len;
1344 		req->seg_id++;
1345 	}
1346 
1347 	release_firmware(fw_entry);
1348 	kfree(req);
1349 	kfree(resp);
1350 	return 0;
1351 
1352 err_send:
1353 	release_firmware(fw_entry);
1354 err_req_fw:
1355 
1356 	kfree(req);
1357 	kfree(resp);
1358 	return ret;
1359 }
1360 
1361 static int wlfw_send_qdss_trace_mode_req
1362 		(struct cnss_plat_data *plat_priv,
1363 		 enum wlfw_qdss_trace_mode_enum_v01 mode,
1364 		 unsigned long long option)
1365 {
1366 	int rc = 0;
1367 	int tmp = 0;
1368 	struct wlfw_qdss_trace_mode_req_msg_v01 *req;
1369 	struct wlfw_qdss_trace_mode_resp_msg_v01 *resp;
1370 	struct qmi_txn txn;
1371 
1372 	if (!plat_priv)
1373 		return -ENODEV;
1374 
1375 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1376 	if (!req)
1377 		return -ENOMEM;
1378 
1379 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1380 	if (!resp) {
1381 		kfree(req);
1382 		return -ENOMEM;
1383 	}
1384 
1385 	req->mode_valid = 1;
1386 	req->mode = mode;
1387 	req->option_valid = 1;
1388 	req->option = option;
1389 
1390 	tmp = plat_priv->hw_trc_override;
1391 
1392 	req->hw_trc_disable_override_valid = 1;
1393 	req->hw_trc_disable_override =
1394 	(tmp > QMI_PARAM_DISABLE_V01 ? QMI_PARAM_DISABLE_V01 :
1395 		 (tmp < 0 ? QMI_PARAM_INVALID_V01 : tmp));
1396 
1397 	cnss_pr_dbg("%s: mode %u, option %llu, hw_trc_disable_override: %u",
1398 		    __func__, mode, option, req->hw_trc_disable_override);
1399 
1400 	rc = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1401 			  wlfw_qdss_trace_mode_resp_msg_v01_ei, resp);
1402 	if (rc < 0) {
1403 		cnss_pr_err("Fail to init txn for QDSS Mode resp %d\n",
1404 			    rc);
1405 		goto out;
1406 	}
1407 
1408 	rc = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1409 			      QMI_WLFW_QDSS_TRACE_MODE_REQ_V01,
1410 			      WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN,
1411 			      wlfw_qdss_trace_mode_req_msg_v01_ei, req);
1412 	if (rc < 0) {
1413 		qmi_txn_cancel(&txn);
1414 		cnss_pr_err("Fail to send QDSS Mode req %d\n", rc);
1415 		goto out;
1416 	}
1417 
1418 	rc = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout);
1419 	if (rc < 0) {
1420 		cnss_pr_err("QDSS Mode resp wait failed with rc %d\n",
1421 			    rc);
1422 		goto out;
1423 	} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1424 		cnss_pr_err("QMI QDSS Mode request rejected, result:%d error:%d\n",
1425 			    resp->resp.result, resp->resp.error);
1426 		rc = -resp->resp.result;
1427 		goto out;
1428 	}
1429 
1430 	kfree(resp);
1431 	kfree(req);
1432 	return rc;
1433 out:
1434 	kfree(resp);
1435 	kfree(req);
1436 	CNSS_QMI_ASSERT();
1437 	return rc;
1438 }
1439 
1440 int wlfw_qdss_trace_start(struct cnss_plat_data *plat_priv)
1441 {
1442 	return wlfw_send_qdss_trace_mode_req(plat_priv,
1443 					     QMI_WLFW_QDSS_TRACE_ON_V01, 0);
1444 }
1445 
1446 int wlfw_qdss_trace_stop(struct cnss_plat_data *plat_priv, unsigned long long option)
1447 {
1448 	return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_OFF_V01,
1449 					     option);
1450 }
1451 
1452 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
1453 				  enum cnss_driver_mode mode)
1454 {
1455 	struct wlfw_wlan_mode_req_msg_v01 *req;
1456 	struct wlfw_wlan_mode_resp_msg_v01 *resp;
1457 	struct qmi_txn txn;
1458 	int ret = 0;
1459 
1460 	if (!plat_priv)
1461 		return -ENODEV;
1462 
1463 	cnss_pr_dbg("Sending mode message, mode: %s(%d), state: 0x%lx\n",
1464 		    cnss_qmi_mode_to_str(mode), mode, plat_priv->driver_state);
1465 
1466 	if (mode == CNSS_OFF &&
1467 	    test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
1468 		cnss_pr_dbg("Recovery is in progress, ignore mode off request\n");
1469 		return 0;
1470 	}
1471 
1472 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1473 	if (!req)
1474 		return -ENOMEM;
1475 
1476 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1477 	if (!resp) {
1478 		kfree(req);
1479 		return -ENOMEM;
1480 	}
1481 
1482 	req->mode = (enum wlfw_driver_mode_enum_v01)mode;
1483 	req->hw_debug_valid = 1;
1484 	req->hw_debug = 0;
1485 
1486 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1487 			   wlfw_wlan_mode_resp_msg_v01_ei, resp);
1488 	if (ret < 0) {
1489 		cnss_pr_err("Failed to initialize txn for mode request, mode: %s(%d), err: %d\n",
1490 			    cnss_qmi_mode_to_str(mode), mode, ret);
1491 		goto out;
1492 	}
1493 
1494 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1495 			       QMI_WLFW_WLAN_MODE_REQ_V01,
1496 			       WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN,
1497 			       wlfw_wlan_mode_req_msg_v01_ei, req);
1498 	if (ret < 0) {
1499 		qmi_txn_cancel(&txn);
1500 		cnss_pr_err("Failed to send mode request, mode: %s(%d), err: %d\n",
1501 			    cnss_qmi_mode_to_str(mode), mode, ret);
1502 		goto out;
1503 	}
1504 
1505 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1506 	if (ret < 0) {
1507 		cnss_pr_err("Failed to wait for response of mode request, mode: %s(%d), err: %d\n",
1508 			    cnss_qmi_mode_to_str(mode), mode, ret);
1509 		goto out;
1510 	}
1511 
1512 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1513 		cnss_pr_err("Mode request failed, mode: %s(%d), result: %d, err: %d\n",
1514 			    cnss_qmi_mode_to_str(mode), mode, resp->resp.result,
1515 			    resp->resp.error);
1516 		ret = -resp->resp.result;
1517 		goto out;
1518 	}
1519 
1520 	kfree(req);
1521 	kfree(resp);
1522 	return 0;
1523 
1524 out:
1525 	if (mode == CNSS_OFF) {
1526 		cnss_pr_dbg("WLFW service is disconnected while sending mode off request\n");
1527 		ret = 0;
1528 	} else {
1529 		CNSS_QMI_ASSERT();
1530 	}
1531 	kfree(req);
1532 	kfree(resp);
1533 	return ret;
1534 }
1535 
1536 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
1537 				 struct cnss_wlan_enable_cfg *config,
1538 				 const char *host_version)
1539 {
1540 	struct wlfw_wlan_cfg_req_msg_v01 *req;
1541 	struct wlfw_wlan_cfg_resp_msg_v01 *resp;
1542 	struct qmi_txn txn;
1543 	u32 i;
1544 	int ret = 0;
1545 
1546 	if (!plat_priv)
1547 		return -ENODEV;
1548 
1549 	cnss_pr_dbg("Sending WLAN config message, state: 0x%lx\n",
1550 		    plat_priv->driver_state);
1551 
1552 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1553 	if (!req)
1554 		return -ENOMEM;
1555 
1556 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1557 	if (!resp) {
1558 		kfree(req);
1559 		return -ENOMEM;
1560 	}
1561 
1562 	req->host_version_valid = 1;
1563 	strlcpy(req->host_version, host_version,
1564 		QMI_WLFW_MAX_STR_LEN_V01 + 1);
1565 
1566 	req->tgt_cfg_valid = 1;
1567 	if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
1568 		req->tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
1569 	else
1570 		req->tgt_cfg_len = config->num_ce_tgt_cfg;
1571 	for (i = 0; i < req->tgt_cfg_len; i++) {
1572 		req->tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
1573 		req->tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
1574 		req->tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
1575 		req->tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
1576 		req->tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
1577 	}
1578 
1579 	req->svc_cfg_valid = 1;
1580 	if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
1581 		req->svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
1582 	else
1583 		req->svc_cfg_len = config->num_ce_svc_pipe_cfg;
1584 	for (i = 0; i < req->svc_cfg_len; i++) {
1585 		req->svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
1586 		req->svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
1587 		req->svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
1588 	}
1589 
1590 	if (plat_priv->device_id != KIWI_DEVICE_ID &&
1591 	    plat_priv->device_id != MANGO_DEVICE_ID) {
1592 		req->shadow_reg_v2_valid = 1;
1593 		if (config->num_shadow_reg_v2_cfg >
1594 		    QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
1595 			req->shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
1596 		else
1597 			req->shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
1598 
1599 		memcpy(req->shadow_reg_v2, config->shadow_reg_v2_cfg,
1600 		       sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
1601 		       * req->shadow_reg_v2_len);
1602 	} else {
1603 		req->shadow_reg_v3_valid = 1;
1604 		if (config->num_shadow_reg_v3_cfg >
1605 		    MAX_NUM_SHADOW_REG_V3)
1606 			req->shadow_reg_v3_len = MAX_NUM_SHADOW_REG_V3;
1607 		else
1608 			req->shadow_reg_v3_len = config->num_shadow_reg_v3_cfg;
1609 
1610 		plat_priv->num_shadow_regs_v3 = req->shadow_reg_v3_len;
1611 
1612 		cnss_pr_dbg("Shadow reg v3 len: %d\n",
1613 			    plat_priv->num_shadow_regs_v3);
1614 
1615 		memcpy(req->shadow_reg_v3, config->shadow_reg_v3_cfg,
1616 		       sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01)
1617 		       * req->shadow_reg_v3_len);
1618 	}
1619 
1620 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1621 			   wlfw_wlan_cfg_resp_msg_v01_ei, resp);
1622 	if (ret < 0) {
1623 		cnss_pr_err("Failed to initialize txn for WLAN config request, err: %d\n",
1624 			    ret);
1625 		goto out;
1626 	}
1627 
1628 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1629 			       QMI_WLFW_WLAN_CFG_REQ_V01,
1630 			       WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN,
1631 			       wlfw_wlan_cfg_req_msg_v01_ei, req);
1632 	if (ret < 0) {
1633 		qmi_txn_cancel(&txn);
1634 		cnss_pr_err("Failed to send WLAN config request, err: %d\n",
1635 			    ret);
1636 		goto out;
1637 	}
1638 
1639 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1640 	if (ret < 0) {
1641 		cnss_pr_err("Failed to wait for response of WLAN config request, err: %d\n",
1642 			    ret);
1643 		goto out;
1644 	}
1645 
1646 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1647 		cnss_pr_err("WLAN config request failed, result: %d, err: %d\n",
1648 			    resp->resp.result, resp->resp.error);
1649 		ret = -resp->resp.result;
1650 		goto out;
1651 	}
1652 
1653 	kfree(req);
1654 	kfree(resp);
1655 	return 0;
1656 
1657 out:
1658 	CNSS_QMI_ASSERT();
1659 	kfree(req);
1660 	kfree(resp);
1661 	return ret;
1662 }
1663 
1664 int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
1665 				     u32 offset, u32 mem_type,
1666 				     u32 data_len, u8 *data)
1667 {
1668 	struct wlfw_athdiag_read_req_msg_v01 *req;
1669 	struct wlfw_athdiag_read_resp_msg_v01 *resp;
1670 	struct qmi_txn txn;
1671 	int ret = 0;
1672 
1673 	if (!plat_priv)
1674 		return -ENODEV;
1675 
1676 	if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
1677 		cnss_pr_err("Invalid parameters for athdiag read: data %pK, data_len %u\n",
1678 			    data, data_len);
1679 		return -EINVAL;
1680 	}
1681 
1682 	cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n",
1683 		    plat_priv->driver_state, offset, mem_type, data_len);
1684 
1685 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1686 	if (!req)
1687 		return -ENOMEM;
1688 
1689 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1690 	if (!resp) {
1691 		kfree(req);
1692 		return -ENOMEM;
1693 	}
1694 
1695 	req->offset = offset;
1696 	req->mem_type = mem_type;
1697 	req->data_len = data_len;
1698 
1699 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1700 			   wlfw_athdiag_read_resp_msg_v01_ei, resp);
1701 	if (ret < 0) {
1702 		cnss_pr_err("Failed to initialize txn for athdiag read request, err: %d\n",
1703 			    ret);
1704 		goto out;
1705 	}
1706 
1707 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1708 			       QMI_WLFW_ATHDIAG_READ_REQ_V01,
1709 			       WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN,
1710 			       wlfw_athdiag_read_req_msg_v01_ei, req);
1711 	if (ret < 0) {
1712 		qmi_txn_cancel(&txn);
1713 		cnss_pr_err("Failed to send athdiag read request, err: %d\n",
1714 			    ret);
1715 		goto out;
1716 	}
1717 
1718 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1719 	if (ret < 0) {
1720 		cnss_pr_err("Failed to wait for response of athdiag read request, err: %d\n",
1721 			    ret);
1722 		goto out;
1723 	}
1724 
1725 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1726 		cnss_pr_err("Athdiag read request failed, result: %d, err: %d\n",
1727 			    resp->resp.result, resp->resp.error);
1728 		ret = -resp->resp.result;
1729 		goto out;
1730 	}
1731 
1732 	if (!resp->data_valid || resp->data_len != data_len) {
1733 		cnss_pr_err("athdiag read data is invalid, data_valid = %u, data_len = %u\n",
1734 			    resp->data_valid, resp->data_len);
1735 		ret = -EINVAL;
1736 		goto out;
1737 	}
1738 
1739 	memcpy(data, resp->data, resp->data_len);
1740 
1741 	kfree(req);
1742 	kfree(resp);
1743 	return 0;
1744 
1745 out:
1746 	kfree(req);
1747 	kfree(resp);
1748 	return ret;
1749 }
1750 
1751 int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
1752 				      u32 offset, u32 mem_type,
1753 				      u32 data_len, u8 *data)
1754 {
1755 	struct wlfw_athdiag_write_req_msg_v01 *req;
1756 	struct wlfw_athdiag_write_resp_msg_v01 *resp;
1757 	struct qmi_txn txn;
1758 	int ret = 0;
1759 
1760 	if (!plat_priv)
1761 		return -ENODEV;
1762 
1763 	if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
1764 		cnss_pr_err("Invalid parameters for athdiag write: data %pK, data_len %u\n",
1765 			    data, data_len);
1766 		return -EINVAL;
1767 	}
1768 
1769 	cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %pK\n",
1770 		    plat_priv->driver_state, offset, mem_type, data_len, data);
1771 
1772 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1773 	if (!req)
1774 		return -ENOMEM;
1775 
1776 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1777 	if (!resp) {
1778 		kfree(req);
1779 		return -ENOMEM;
1780 	}
1781 
1782 	req->offset = offset;
1783 	req->mem_type = mem_type;
1784 	req->data_len = data_len;
1785 	memcpy(req->data, data, data_len);
1786 
1787 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1788 			   wlfw_athdiag_write_resp_msg_v01_ei, resp);
1789 	if (ret < 0) {
1790 		cnss_pr_err("Failed to initialize txn for athdiag write request, err: %d\n",
1791 			    ret);
1792 		goto out;
1793 	}
1794 
1795 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1796 			       QMI_WLFW_ATHDIAG_WRITE_REQ_V01,
1797 			       WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN,
1798 			       wlfw_athdiag_write_req_msg_v01_ei, req);
1799 	if (ret < 0) {
1800 		qmi_txn_cancel(&txn);
1801 		cnss_pr_err("Failed to send athdiag write request, err: %d\n",
1802 			    ret);
1803 		goto out;
1804 	}
1805 
1806 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1807 	if (ret < 0) {
1808 		cnss_pr_err("Failed to wait for response of athdiag write request, err: %d\n",
1809 			    ret);
1810 		goto out;
1811 	}
1812 
1813 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1814 		cnss_pr_err("Athdiag write request failed, result: %d, err: %d\n",
1815 			    resp->resp.result, resp->resp.error);
1816 		ret = -resp->resp.result;
1817 		goto out;
1818 	}
1819 
1820 	kfree(req);
1821 	kfree(resp);
1822 	return 0;
1823 
1824 out:
1825 	kfree(req);
1826 	kfree(resp);
1827 	return ret;
1828 }
1829 
1830 int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
1831 			    u8 fw_log_mode)
1832 {
1833 	struct wlfw_ini_req_msg_v01 *req;
1834 	struct wlfw_ini_resp_msg_v01 *resp;
1835 	struct qmi_txn txn;
1836 	int ret = 0;
1837 
1838 	if (!plat_priv)
1839 		return -ENODEV;
1840 
1841 	cnss_pr_dbg("Sending ini sync request, state: 0x%lx, fw_log_mode: %d\n",
1842 		    plat_priv->driver_state, fw_log_mode);
1843 
1844 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1845 	if (!req)
1846 		return -ENOMEM;
1847 
1848 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1849 	if (!resp) {
1850 		kfree(req);
1851 		return -ENOMEM;
1852 	}
1853 
1854 	req->enablefwlog_valid = 1;
1855 	req->enablefwlog = fw_log_mode;
1856 
1857 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1858 			   wlfw_ini_resp_msg_v01_ei, resp);
1859 	if (ret < 0) {
1860 		cnss_pr_err("Failed to initialize txn for ini request, fw_log_mode: %d, err: %d\n",
1861 			    fw_log_mode, ret);
1862 		goto out;
1863 	}
1864 
1865 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1866 			       QMI_WLFW_INI_REQ_V01,
1867 			       WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
1868 			       wlfw_ini_req_msg_v01_ei, req);
1869 	if (ret < 0) {
1870 		qmi_txn_cancel(&txn);
1871 		cnss_pr_err("Failed to send ini request, fw_log_mode: %d, err: %d\n",
1872 			    fw_log_mode, ret);
1873 		goto out;
1874 	}
1875 
1876 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1877 	if (ret < 0) {
1878 		cnss_pr_err("Failed to wait for response of ini request, fw_log_mode: %d, err: %d\n",
1879 			    fw_log_mode, ret);
1880 		goto out;
1881 	}
1882 
1883 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
1884 		cnss_pr_err("Ini request failed, fw_log_mode: %d, result: %d, err: %d\n",
1885 			    fw_log_mode, resp->resp.result, resp->resp.error);
1886 		ret = -resp->resp.result;
1887 		goto out;
1888 	}
1889 
1890 	kfree(req);
1891 	kfree(resp);
1892 	return 0;
1893 
1894 out:
1895 	kfree(req);
1896 	kfree(resp);
1897 	return ret;
1898 }
1899 
1900 int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv)
1901 {
1902 	struct wlfw_pcie_gen_switch_req_msg_v01 req;
1903 	struct wlfw_pcie_gen_switch_resp_msg_v01 resp = {0};
1904 	struct qmi_txn txn;
1905 	int ret = 0;
1906 
1907 	if (!plat_priv)
1908 		return -ENODEV;
1909 
1910 	if (plat_priv->pcie_gen_speed == QMI_PCIE_GEN_SPEED_INVALID_V01 ||
1911 	    !plat_priv->fw_pcie_gen_switch) {
1912 		cnss_pr_dbg("PCIE Gen speed not setup\n");
1913 		return 0;
1914 	}
1915 
1916 	cnss_pr_dbg("Sending PCIE Gen speed: %d state: 0x%lx\n",
1917 		    plat_priv->pcie_gen_speed, plat_priv->driver_state);
1918 	req.pcie_speed = (enum wlfw_pcie_gen_speed_v01)
1919 			plat_priv->pcie_gen_speed;
1920 
1921 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1922 			   wlfw_pcie_gen_switch_resp_msg_v01_ei, &resp);
1923 	if (ret < 0) {
1924 		cnss_pr_err("Failed to initialize txn for PCIE speed switch err: %d\n",
1925 			    ret);
1926 		goto out;
1927 	}
1928 
1929 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1930 			       QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01,
1931 			       WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN,
1932 			       wlfw_pcie_gen_switch_req_msg_v01_ei, &req);
1933 	if (ret < 0) {
1934 		qmi_txn_cancel(&txn);
1935 		cnss_pr_err("Failed to send PCIE speed switch, err: %d\n", ret);
1936 		goto out;
1937 	}
1938 
1939 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
1940 	if (ret < 0) {
1941 		cnss_pr_err("Failed to wait for PCIE Gen switch resp, err: %d\n",
1942 			    ret);
1943 		goto out;
1944 	}
1945 
1946 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
1947 		cnss_pr_err("PCIE Gen Switch req failed, Speed: %d, result: %d, err: %d\n",
1948 			    plat_priv->pcie_gen_speed, resp.resp.result,
1949 			    resp.resp.error);
1950 		ret = -resp.resp.result;
1951 	}
1952 out:
1953 	/* Reset PCIE Gen speed after one time use */
1954 	plat_priv->pcie_gen_speed = QMI_PCIE_GEN_SPEED_INVALID_V01;
1955 	return ret;
1956 }
1957 
1958 int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv)
1959 {
1960 	struct wlfw_antenna_switch_req_msg_v01 *req;
1961 	struct wlfw_antenna_switch_resp_msg_v01 *resp;
1962 	struct qmi_txn txn;
1963 	int ret = 0;
1964 
1965 	if (!plat_priv)
1966 		return -ENODEV;
1967 
1968 	cnss_pr_dbg("Sending antenna switch sync request, state: 0x%lx\n",
1969 		    plat_priv->driver_state);
1970 
1971 	req = kzalloc(sizeof(*req), GFP_KERNEL);
1972 	if (!req)
1973 		return -ENOMEM;
1974 
1975 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
1976 	if (!resp) {
1977 		kfree(req);
1978 		return -ENOMEM;
1979 	}
1980 
1981 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
1982 			   wlfw_antenna_switch_resp_msg_v01_ei, resp);
1983 	if (ret < 0) {
1984 		cnss_pr_err("Failed to initialize txn for antenna switch request, err: %d\n",
1985 			    ret);
1986 		goto out;
1987 	}
1988 
1989 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
1990 			       QMI_WLFW_ANTENNA_SWITCH_REQ_V01,
1991 			       WLFW_ANTENNA_SWITCH_REQ_MSG_V01_MAX_MSG_LEN,
1992 			       wlfw_antenna_switch_req_msg_v01_ei, req);
1993 	if (ret < 0) {
1994 		qmi_txn_cancel(&txn);
1995 		cnss_pr_err("Failed to send antenna switch request, err: %d\n",
1996 			    ret);
1997 		goto out;
1998 	}
1999 
2000 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2001 	if (ret < 0) {
2002 		cnss_pr_err("Failed to wait for response of antenna switch request, err: %d\n",
2003 			    ret);
2004 		goto out;
2005 	}
2006 
2007 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2008 		cnss_pr_dbg("Antenna switch request failed, result: %d, err: %d\n",
2009 			    resp->resp.result, resp->resp.error);
2010 		ret = -resp->resp.result;
2011 		goto out;
2012 	}
2013 
2014 	if (resp->antenna_valid)
2015 		plat_priv->antenna = resp->antenna;
2016 
2017 	cnss_pr_dbg("Antenna valid: %u, antenna 0x%llx\n",
2018 		    resp->antenna_valid, resp->antenna);
2019 
2020 	kfree(req);
2021 	kfree(resp);
2022 	return 0;
2023 
2024 out:
2025 	kfree(req);
2026 	kfree(resp);
2027 	return ret;
2028 }
2029 
2030 int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv)
2031 {
2032 	struct wlfw_antenna_grant_req_msg_v01 *req;
2033 	struct wlfw_antenna_grant_resp_msg_v01 *resp;
2034 	struct qmi_txn txn;
2035 	int ret = 0;
2036 
2037 	if (!plat_priv)
2038 		return -ENODEV;
2039 
2040 	cnss_pr_dbg("Sending antenna grant sync request, state: 0x%lx, grant 0x%llx\n",
2041 		    plat_priv->driver_state, plat_priv->grant);
2042 
2043 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2044 	if (!req)
2045 		return -ENOMEM;
2046 
2047 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2048 	if (!resp) {
2049 		kfree(req);
2050 		return -ENOMEM;
2051 	}
2052 
2053 	req->grant_valid = 1;
2054 	req->grant = plat_priv->grant;
2055 
2056 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2057 			   wlfw_antenna_grant_resp_msg_v01_ei, resp);
2058 	if (ret < 0) {
2059 		cnss_pr_err("Failed to initialize txn for antenna grant request, err: %d\n",
2060 			    ret);
2061 		goto out;
2062 	}
2063 
2064 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2065 			       QMI_WLFW_ANTENNA_GRANT_REQ_V01,
2066 			       WLFW_ANTENNA_GRANT_REQ_MSG_V01_MAX_MSG_LEN,
2067 			       wlfw_antenna_grant_req_msg_v01_ei, req);
2068 	if (ret < 0) {
2069 		qmi_txn_cancel(&txn);
2070 		cnss_pr_err("Failed to send antenna grant request, err: %d\n",
2071 			    ret);
2072 		goto out;
2073 	}
2074 
2075 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2076 	if (ret < 0) {
2077 		cnss_pr_err("Failed to wait for response of antenna grant request, err: %d\n",
2078 			    ret);
2079 		goto out;
2080 	}
2081 
2082 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2083 		cnss_pr_err("Antenna grant request failed, result: %d, err: %d\n",
2084 			    resp->resp.result, resp->resp.error);
2085 		ret = -resp->resp.result;
2086 		goto out;
2087 	}
2088 
2089 	kfree(req);
2090 	kfree(resp);
2091 	return 0;
2092 
2093 out:
2094 	kfree(req);
2095 	kfree(resp);
2096 	return ret;
2097 }
2098 
2099 int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv)
2100 {
2101 	struct wlfw_qdss_trace_mem_info_req_msg_v01 *req;
2102 	struct wlfw_qdss_trace_mem_info_resp_msg_v01 *resp;
2103 	struct qmi_txn txn;
2104 	struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem;
2105 	int ret = 0;
2106 	int i;
2107 
2108 	cnss_pr_dbg("Sending QDSS trace mem info, state: 0x%lx\n",
2109 		    plat_priv->driver_state);
2110 
2111 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2112 	if (!req)
2113 		return -ENOMEM;
2114 
2115 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2116 	if (!resp) {
2117 		kfree(req);
2118 		return -ENOMEM;
2119 	}
2120 
2121 	if (plat_priv->qdss_mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) {
2122 		cnss_pr_err("Invalid seg len %u\n", plat_priv->qdss_mem_seg_len);
2123 		ret = -EINVAL;
2124 		goto out;
2125 	}
2126 
2127 	req->mem_seg_len = plat_priv->qdss_mem_seg_len;
2128 	for (i = 0; i < req->mem_seg_len; i++) {
2129 		cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n",
2130 			    qdss_mem[i].va, &qdss_mem[i].pa,
2131 			    qdss_mem[i].size, qdss_mem[i].type);
2132 
2133 		req->mem_seg[i].addr = qdss_mem[i].pa;
2134 		req->mem_seg[i].size = qdss_mem[i].size;
2135 		req->mem_seg[i].type = qdss_mem[i].type;
2136 	}
2137 
2138 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2139 			   wlfw_qdss_trace_mem_info_resp_msg_v01_ei, resp);
2140 	if (ret < 0) {
2141 		cnss_pr_err("Fail to initialize txn for QDSS trace mem request: err %d\n",
2142 			    ret);
2143 		goto out;
2144 	}
2145 
2146 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2147 			       QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01,
2148 			       WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN,
2149 			       wlfw_qdss_trace_mem_info_req_msg_v01_ei, req);
2150 	if (ret < 0) {
2151 		qmi_txn_cancel(&txn);
2152 		cnss_pr_err("Fail to send QDSS trace mem info request: err %d\n",
2153 			    ret);
2154 		goto out;
2155 	}
2156 
2157 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2158 	if (ret < 0) {
2159 		cnss_pr_err("Fail to wait for response of QDSS trace mem info request, err %d\n",
2160 			    ret);
2161 		goto out;
2162 	}
2163 
2164 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2165 		cnss_pr_err("QDSS trace mem info request failed, result: %d, err: %d\n",
2166 			    resp->resp.result, resp->resp.error);
2167 		ret = -resp->resp.result;
2168 		goto out;
2169 	}
2170 
2171 	kfree(req);
2172 	kfree(resp);
2173 	return 0;
2174 
2175 out:
2176 	kfree(req);
2177 	kfree(resp);
2178 	return ret;
2179 }
2180 
2181 int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv,
2182 					struct cnss_wfc_cfg cfg)
2183 {
2184 	struct wlfw_wfc_call_status_req_msg_v01 *req;
2185 	struct wlfw_wfc_call_status_resp_msg_v01 *resp;
2186 	struct qmi_txn txn;
2187 	int ret = 0;
2188 
2189 	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
2190 		cnss_pr_err("Drop host WFC indication as FW not initialized\n");
2191 		return -EINVAL;
2192 	}
2193 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2194 	if (!req)
2195 		return -ENOMEM;
2196 
2197 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2198 	if (!resp) {
2199 		kfree(req);
2200 		return -ENOMEM;
2201 	}
2202 
2203 	req->wfc_call_active_valid = 1;
2204 	req->wfc_call_active = cfg.mode;
2205 
2206 	cnss_pr_dbg("CNSS->FW: WFC_CALL_REQ: state: 0x%lx\n",
2207 		    plat_priv->driver_state);
2208 
2209 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2210 			   wlfw_wfc_call_status_resp_msg_v01_ei, resp);
2211 	if (ret < 0) {
2212 		cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Txn Init: Err %d\n",
2213 			    ret);
2214 		goto out;
2215 	}
2216 
2217 	cnss_pr_dbg("Send WFC Mode: %d\n", cfg.mode);
2218 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2219 			       QMI_WLFW_WFC_CALL_STATUS_REQ_V01,
2220 			       WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN,
2221 			       wlfw_wfc_call_status_req_msg_v01_ei, req);
2222 	if (ret < 0) {
2223 		qmi_txn_cancel(&txn);
2224 		cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Send Err: %d\n",
2225 			    ret);
2226 		goto out;
2227 	}
2228 
2229 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2230 	if (ret < 0) {
2231 		cnss_pr_err("FW->CNSS: WFC_CALL_RSP: QMI Wait Err: %d\n",
2232 			    ret);
2233 		goto out;
2234 	}
2235 
2236 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2237 		cnss_pr_err("FW->CNSS: WFC_CALL_RSP: Result: %d Err: %d\n",
2238 			    resp->resp.result, resp->resp.error);
2239 		ret = -EINVAL;
2240 		goto out;
2241 	}
2242 	ret = 0;
2243 out:
2244 	kfree(req);
2245 	kfree(resp);
2246 	return ret;
2247 
2248 }
2249 static int cnss_wlfw_wfc_call_status_send_sync
2250 	(struct cnss_plat_data *plat_priv,
2251 	 const struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg)
2252 {
2253 	struct wlfw_wfc_call_status_req_msg_v01 *req;
2254 	struct wlfw_wfc_call_status_resp_msg_v01 *resp;
2255 	struct qmi_txn txn;
2256 	int ret = 0;
2257 
2258 	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
2259 		cnss_pr_err("Drop IMS WFC indication as FW not initialized\n");
2260 		return -EINVAL;
2261 	}
2262 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2263 	if (!req)
2264 		return -ENOMEM;
2265 
2266 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2267 	if (!resp) {
2268 		kfree(req);
2269 		return -ENOMEM;
2270 	}
2271 
2272 	/**
2273 	 * WFC Call r1 design has CNSS as pass thru using opaque hex buffer.
2274 	 * But in r2 update QMI structure is expanded and as an effect qmi
2275 	 * decoded structures have padding. Thus we cannot use buffer design.
2276 	 * For backward compatibility for r1 design copy only wfc_call_active
2277 	 * value in hex buffer.
2278 	 */
2279 	req->wfc_call_status_len = sizeof(ind_msg->wfc_call_active);
2280 	req->wfc_call_status[0] = ind_msg->wfc_call_active;
2281 
2282 	/* wfc_call_active is mandatory in IMS indication */
2283 	req->wfc_call_active_valid = 1;
2284 	req->wfc_call_active = ind_msg->wfc_call_active;
2285 	req->all_wfc_calls_held_valid = ind_msg->all_wfc_calls_held_valid;
2286 	req->all_wfc_calls_held = ind_msg->all_wfc_calls_held;
2287 	req->is_wfc_emergency_valid = ind_msg->is_wfc_emergency_valid;
2288 	req->is_wfc_emergency = ind_msg->is_wfc_emergency;
2289 	req->twt_ims_start_valid = ind_msg->twt_ims_start_valid;
2290 	req->twt_ims_start = ind_msg->twt_ims_start;
2291 	req->twt_ims_int_valid = ind_msg->twt_ims_int_valid;
2292 	req->twt_ims_int = ind_msg->twt_ims_int;
2293 	req->media_quality_valid = ind_msg->media_quality_valid;
2294 	req->media_quality =
2295 		(enum wlfw_wfc_media_quality_v01)ind_msg->media_quality;
2296 
2297 	cnss_pr_dbg("CNSS->FW: WFC_CALL_REQ: state: 0x%lx\n",
2298 		    plat_priv->driver_state);
2299 
2300 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2301 			   wlfw_wfc_call_status_resp_msg_v01_ei, resp);
2302 	if (ret < 0) {
2303 		cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Txn Init: Err %d\n",
2304 			    ret);
2305 		goto out;
2306 	}
2307 
2308 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2309 			       QMI_WLFW_WFC_CALL_STATUS_REQ_V01,
2310 			       WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN,
2311 			       wlfw_wfc_call_status_req_msg_v01_ei, req);
2312 	if (ret < 0) {
2313 		qmi_txn_cancel(&txn);
2314 		cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Send Err: %d\n",
2315 			    ret);
2316 		goto out;
2317 	}
2318 
2319 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2320 	if (ret < 0) {
2321 		cnss_pr_err("FW->CNSS: WFC_CALL_RSP: QMI Wait Err: %d\n",
2322 			    ret);
2323 		goto out;
2324 	}
2325 
2326 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2327 		cnss_pr_err("FW->CNSS: WFC_CALL_RSP: Result: %d Err: %d\n",
2328 			    resp->resp.result, resp->resp.error);
2329 		ret = -resp->resp.result;
2330 		goto out;
2331 	}
2332 	ret = 0;
2333 out:
2334 	kfree(req);
2335 	kfree(resp);
2336 	return ret;
2337 }
2338 
2339 int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv)
2340 {
2341 	struct wlfw_dynamic_feature_mask_req_msg_v01 *req;
2342 	struct wlfw_dynamic_feature_mask_resp_msg_v01 *resp;
2343 	struct qmi_txn txn;
2344 	int ret = 0;
2345 
2346 	cnss_pr_dbg("Sending dynamic feature mask 0x%llx, state: 0x%lx\n",
2347 		    plat_priv->dynamic_feature,
2348 		    plat_priv->driver_state);
2349 
2350 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2351 	if (!req)
2352 		return -ENOMEM;
2353 
2354 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2355 	if (!resp) {
2356 		kfree(req);
2357 		return -ENOMEM;
2358 	}
2359 
2360 	req->mask_valid = 1;
2361 	req->mask = plat_priv->dynamic_feature;
2362 
2363 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2364 			   wlfw_dynamic_feature_mask_resp_msg_v01_ei, resp);
2365 	if (ret < 0) {
2366 		cnss_pr_err("Fail to initialize txn for dynamic feature mask request: err %d\n",
2367 			    ret);
2368 		goto out;
2369 	}
2370 
2371 	ret = qmi_send_request
2372 		(&plat_priv->qmi_wlfw, NULL, &txn,
2373 		 QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01,
2374 		 WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN,
2375 		 wlfw_dynamic_feature_mask_req_msg_v01_ei, req);
2376 	if (ret < 0) {
2377 		qmi_txn_cancel(&txn);
2378 		cnss_pr_err("Fail to send dynamic feature mask request: err %d\n",
2379 			    ret);
2380 		goto out;
2381 	}
2382 
2383 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2384 	if (ret < 0) {
2385 		cnss_pr_err("Fail to wait for response of dynamic feature mask request, err %d\n",
2386 			    ret);
2387 		goto out;
2388 	}
2389 
2390 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2391 		cnss_pr_err("Dynamic feature mask request failed, result: %d, err: %d\n",
2392 			    resp->resp.result, resp->resp.error);
2393 		ret = -resp->resp.result;
2394 		goto out;
2395 	}
2396 
2397 out:
2398 	kfree(req);
2399 	kfree(resp);
2400 	return ret;
2401 }
2402 
2403 int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type,
2404 				 void *cmd, int cmd_len)
2405 {
2406 	struct wlfw_get_info_req_msg_v01 *req;
2407 	struct wlfw_get_info_resp_msg_v01 *resp;
2408 	struct qmi_txn txn;
2409 	int ret = 0;
2410 
2411 	cnss_pr_buf("Sending get info message, type: %d, cmd length: %d, state: 0x%lx\n",
2412 		    type, cmd_len, plat_priv->driver_state);
2413 
2414 	if (cmd_len > QMI_WLFW_MAX_DATA_SIZE_V01)
2415 		return -EINVAL;
2416 
2417 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2418 	if (!req)
2419 		return -ENOMEM;
2420 
2421 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2422 	if (!resp) {
2423 		kfree(req);
2424 		return -ENOMEM;
2425 	}
2426 
2427 	req->type = type;
2428 	req->data_len = cmd_len;
2429 	memcpy(req->data, cmd, req->data_len);
2430 
2431 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2432 			   wlfw_get_info_resp_msg_v01_ei, resp);
2433 	if (ret < 0) {
2434 		cnss_pr_err("Failed to initialize txn for get info request, err: %d\n",
2435 			    ret);
2436 		goto out;
2437 	}
2438 
2439 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2440 			       QMI_WLFW_GET_INFO_REQ_V01,
2441 			       WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN,
2442 			       wlfw_get_info_req_msg_v01_ei, req);
2443 	if (ret < 0) {
2444 		qmi_txn_cancel(&txn);
2445 		cnss_pr_err("Failed to send get info request, err: %d\n",
2446 			    ret);
2447 		goto out;
2448 	}
2449 
2450 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2451 	if (ret < 0) {
2452 		cnss_pr_err("Failed to wait for response of get info request, err: %d\n",
2453 			    ret);
2454 		goto out;
2455 	}
2456 
2457 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2458 		cnss_pr_err("Get info request failed, result: %d, err: %d\n",
2459 			    resp->resp.result, resp->resp.error);
2460 		ret = -resp->resp.result;
2461 		goto out;
2462 	}
2463 
2464 	kfree(req);
2465 	kfree(resp);
2466 	return 0;
2467 
2468 out:
2469 	kfree(req);
2470 	kfree(resp);
2471 	return ret;
2472 }
2473 
2474 unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv)
2475 {
2476 	return QMI_WLFW_TIMEOUT_MS;
2477 }
2478 
2479 static void cnss_wlfw_request_mem_ind_cb(struct qmi_handle *qmi_wlfw,
2480 					 struct sockaddr_qrtr *sq,
2481 					 struct qmi_txn *txn, const void *data)
2482 {
2483 	struct cnss_plat_data *plat_priv =
2484 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2485 	const struct wlfw_request_mem_ind_msg_v01 *ind_msg = data;
2486 	int i;
2487 
2488 	cnss_pr_dbg("Received QMI WLFW request memory indication\n");
2489 
2490 	if (!txn) {
2491 		cnss_pr_err("Spurious indication\n");
2492 		return;
2493 	}
2494 
2495 	if (ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) {
2496 		cnss_pr_err("Invalid seg len %u\n", ind_msg->mem_seg_len);
2497 		return;
2498 	}
2499 
2500 	plat_priv->fw_mem_seg_len = ind_msg->mem_seg_len;
2501 	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
2502 		cnss_pr_dbg("FW requests for memory, size: 0x%x, type: %u\n",
2503 			    ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type);
2504 		plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type;
2505 		plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size;
2506 		if (!plat_priv->fw_mem[i].va &&
2507 		    plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR)
2508 			plat_priv->fw_mem[i].attrs |=
2509 				DMA_ATTR_FORCE_CONTIGUOUS;
2510 		if (plat_priv->fw_mem[i].type == CNSS_MEM_CAL_V01)
2511 			plat_priv->cal_mem = &plat_priv->fw_mem[i];
2512 	}
2513 
2514 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REQUEST_MEM,
2515 			       0, NULL);
2516 }
2517 
2518 static void cnss_wlfw_fw_mem_ready_ind_cb(struct qmi_handle *qmi_wlfw,
2519 					  struct sockaddr_qrtr *sq,
2520 					  struct qmi_txn *txn, const void *data)
2521 {
2522 	struct cnss_plat_data *plat_priv =
2523 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2524 
2525 	cnss_pr_dbg("Received QMI WLFW FW memory ready indication\n");
2526 
2527 	if (!txn) {
2528 		cnss_pr_err("Spurious indication\n");
2529 		return;
2530 	}
2531 
2532 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_MEM_READY,
2533 			       0, NULL);
2534 }
2535 
2536 /**
2537  * cnss_wlfw_fw_ready_ind_cb: FW ready indication handler (Helium arch)
2538  *
2539  * This event is not required for HST/ HSP as FW calibration done is
2540  * provided in QMI_WLFW_CAL_DONE_IND_V01
2541  */
2542 static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw,
2543 				      struct sockaddr_qrtr *sq,
2544 				      struct qmi_txn *txn, const void *data)
2545 {
2546 	struct cnss_plat_data *plat_priv =
2547 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2548 	struct cnss_cal_info *cal_info;
2549 
2550 	if (!txn) {
2551 		cnss_pr_err("Spurious indication\n");
2552 		return;
2553 	}
2554 
2555 	if (plat_priv->device_id == QCA6390_DEVICE_ID ||
2556 	    plat_priv->device_id == QCA6490_DEVICE_ID) {
2557 		cnss_pr_dbg("Ignore FW Ready Indication for HST/HSP");
2558 		return;
2559 	}
2560 
2561 	cnss_pr_dbg("Received QMI WLFW FW ready indication.\n");
2562 	cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL);
2563 	if (!cal_info)
2564 		return;
2565 
2566 	cal_info->cal_status = CNSS_CAL_DONE;
2567 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE,
2568 			       0, cal_info);
2569 }
2570 
2571 static void cnss_wlfw_fw_init_done_ind_cb(struct qmi_handle *qmi_wlfw,
2572 					  struct sockaddr_qrtr *sq,
2573 					  struct qmi_txn *txn, const void *data)
2574 {
2575 	struct cnss_plat_data *plat_priv =
2576 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2577 
2578 	cnss_pr_dbg("Received QMI WLFW FW initialization done indication\n");
2579 
2580 	if (!txn) {
2581 		cnss_pr_err("Spurious indication\n");
2582 		return;
2583 	}
2584 
2585 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_READY, 0, NULL);
2586 }
2587 
2588 static void cnss_wlfw_pin_result_ind_cb(struct qmi_handle *qmi_wlfw,
2589 					struct sockaddr_qrtr *sq,
2590 					struct qmi_txn *txn, const void *data)
2591 {
2592 	struct cnss_plat_data *plat_priv =
2593 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2594 	const struct wlfw_pin_connect_result_ind_msg_v01 *ind_msg = data;
2595 
2596 	cnss_pr_dbg("Received QMI WLFW pin connect result indication\n");
2597 
2598 	if (!txn) {
2599 		cnss_pr_err("Spurious indication\n");
2600 		return;
2601 	}
2602 
2603 	if (ind_msg->pwr_pin_result_valid)
2604 		plat_priv->pin_result.fw_pwr_pin_result =
2605 		    ind_msg->pwr_pin_result;
2606 	if (ind_msg->phy_io_pin_result_valid)
2607 		plat_priv->pin_result.fw_phy_io_pin_result =
2608 		    ind_msg->phy_io_pin_result;
2609 	if (ind_msg->rf_pin_result_valid)
2610 		plat_priv->pin_result.fw_rf_pin_result = ind_msg->rf_pin_result;
2611 
2612 	cnss_pr_dbg("Pin connect Result: pwr_pin: 0x%x phy_io_pin: 0x%x rf_io_pin: 0x%x\n",
2613 		    ind_msg->pwr_pin_result, ind_msg->phy_io_pin_result,
2614 		    ind_msg->rf_pin_result);
2615 }
2616 
2617 int cnss_wlfw_cal_report_req_send_sync(struct cnss_plat_data *plat_priv,
2618 				       u32 cal_file_download_size)
2619 {
2620 	struct wlfw_cal_report_req_msg_v01 req = {0};
2621 	struct wlfw_cal_report_resp_msg_v01 resp = {0};
2622 	struct qmi_txn txn;
2623 	int ret = 0;
2624 
2625 	cnss_pr_dbg("Sending cal file report request. File size: %d, state: 0x%lx\n",
2626 		    cal_file_download_size, plat_priv->driver_state);
2627 	req.cal_file_download_size_valid = 1;
2628 	req.cal_file_download_size = cal_file_download_size;
2629 
2630 	ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn,
2631 			   wlfw_cal_report_resp_msg_v01_ei, &resp);
2632 	if (ret < 0) {
2633 		cnss_pr_err("Failed to initialize txn for Cal Report request, err: %d\n",
2634 			    ret);
2635 		goto out;
2636 	}
2637 	ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn,
2638 			       QMI_WLFW_CAL_REPORT_REQ_V01,
2639 			       WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN,
2640 			       wlfw_cal_report_req_msg_v01_ei, &req);
2641 	if (ret < 0) {
2642 		qmi_txn_cancel(&txn);
2643 		cnss_pr_err("Failed to send Cal Report request, err: %d\n",
2644 			    ret);
2645 		goto out;
2646 	}
2647 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2648 	if (ret < 0) {
2649 		cnss_pr_err("Failed to wait for response of Cal Report request, err: %d\n",
2650 			    ret);
2651 		goto out;
2652 	}
2653 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
2654 		cnss_pr_err("Cal Report request failed, result: %d, err: %d\n",
2655 			    resp.resp.result, resp.resp.error);
2656 		ret = -resp.resp.result;
2657 		goto out;
2658 	}
2659 out:
2660 	return ret;
2661 }
2662 
2663 static void cnss_wlfw_cal_done_ind_cb(struct qmi_handle *qmi_wlfw,
2664 				      struct sockaddr_qrtr *sq,
2665 				      struct qmi_txn *txn, const void *data)
2666 {
2667 	struct cnss_plat_data *plat_priv =
2668 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2669 	const struct wlfw_cal_done_ind_msg_v01 *ind = data;
2670 	struct cnss_cal_info *cal_info;
2671 
2672 	cnss_pr_dbg("Received Cal done indication. File size: %d\n",
2673 		    ind->cal_file_upload_size);
2674 	cnss_pr_info("Calibration took %d ms\n",
2675 		     jiffies_to_msecs(jiffies - plat_priv->cal_time));
2676 	if (!txn) {
2677 		cnss_pr_err("Spurious indication\n");
2678 		return;
2679 	}
2680 	if (ind->cal_file_upload_size_valid)
2681 		plat_priv->cal_file_size = ind->cal_file_upload_size;
2682 	cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL);
2683 	if (!cal_info)
2684 		return;
2685 
2686 	cal_info->cal_status = CNSS_CAL_DONE;
2687 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE,
2688 			       0, cal_info);
2689 }
2690 
2691 static void cnss_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_wlfw,
2692 						struct sockaddr_qrtr *sq,
2693 						struct qmi_txn *txn,
2694 						const void *data)
2695 {
2696 	struct cnss_plat_data *plat_priv =
2697 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2698 	const struct wlfw_qdss_trace_req_mem_ind_msg_v01 *ind_msg = data;
2699 	int i;
2700 
2701 	cnss_pr_dbg("Received QMI WLFW QDSS trace request mem indication\n");
2702 
2703 	if (!txn) {
2704 		cnss_pr_err("Spurious indication\n");
2705 		return;
2706 	}
2707 
2708 	if (plat_priv->qdss_mem_seg_len) {
2709 		cnss_pr_err("Ignore double allocation for QDSS trace, current len %u\n",
2710 			    plat_priv->qdss_mem_seg_len);
2711 		return;
2712 	}
2713 
2714 	if (ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) {
2715 		cnss_pr_err("Invalid seg len %u\n", ind_msg->mem_seg_len);
2716 		return;
2717 	}
2718 
2719 	plat_priv->qdss_mem_seg_len = ind_msg->mem_seg_len;
2720 	for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) {
2721 		cnss_pr_dbg("QDSS requests for memory, size: 0x%x, type: %u\n",
2722 			    ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type);
2723 		plat_priv->qdss_mem[i].type = ind_msg->mem_seg[i].type;
2724 		plat_priv->qdss_mem[i].size = ind_msg->mem_seg[i].size;
2725 	}
2726 
2727 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM,
2728 			       0, NULL);
2729 }
2730 
2731 /**
2732  * cnss_wlfw_fw_mem_file_save_ind_cb: Save given FW mem to filesystem
2733  *
2734  * QDSS_TRACE_SAVE_IND feature is overloaded to provide any host allocated
2735  * fw memory segment for dumping to file system. Only one type of mem can be
2736  * saved per indication and is provided in mem seg index 0.
2737  *
2738  * Return: None
2739  */
2740 static void cnss_wlfw_fw_mem_file_save_ind_cb(struct qmi_handle *qmi_wlfw,
2741 					      struct sockaddr_qrtr *sq,
2742 					      struct qmi_txn *txn,
2743 					      const void *data)
2744 {
2745 	struct cnss_plat_data *plat_priv =
2746 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2747 	const struct wlfw_qdss_trace_save_ind_msg_v01 *ind_msg = data;
2748 	struct cnss_qmi_event_fw_mem_file_save_data *event_data;
2749 	int i = 0;
2750 
2751 	if (!txn || !data) {
2752 		cnss_pr_err("Spurious indication\n");
2753 		return;
2754 	}
2755 	cnss_pr_dbg("QMI fw_mem_file_save: source: %d  mem_seg: %d type: %u len: %u\n",
2756 		    ind_msg->source, ind_msg->mem_seg_valid,
2757 		    ind_msg->mem_seg[0].type, ind_msg->mem_seg_len);
2758 
2759 	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
2760 	if (!event_data)
2761 		return;
2762 
2763 	event_data->mem_type = ind_msg->mem_seg[0].type;
2764 	event_data->mem_seg_len = ind_msg->mem_seg_len;
2765 	event_data->total_size = ind_msg->total_size;
2766 
2767 	if (ind_msg->mem_seg_valid) {
2768 		if (ind_msg->mem_seg_len > QMI_WLFW_MAX_STR_LEN_V01) {
2769 			cnss_pr_err("Invalid seg len indication\n");
2770 			goto free_event_data;
2771 		}
2772 		for (i = 0; i < ind_msg->mem_seg_len; i++) {
2773 			event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr;
2774 			event_data->mem_seg[i].size = ind_msg->mem_seg[i].size;
2775 			if (event_data->mem_type != ind_msg->mem_seg[i].type) {
2776 				cnss_pr_err("FW Mem file save ind cannot have multiple mem types\n");
2777 				goto free_event_data;
2778 			}
2779 			cnss_pr_dbg("seg-%d: addr 0x%llx size 0x%x\n",
2780 				    i, ind_msg->mem_seg[i].addr,
2781 				    ind_msg->mem_seg[i].size);
2782 		}
2783 	}
2784 
2785 	if (ind_msg->file_name_valid)
2786 		strlcpy(event_data->file_name, ind_msg->file_name,
2787 			QMI_WLFW_MAX_STR_LEN_V01 + 1);
2788 	if (ind_msg->source == 1) {
2789 		if (!ind_msg->file_name_valid)
2790 			strlcpy(event_data->file_name, "qdss_trace_wcss_etb",
2791 				QMI_WLFW_MAX_STR_LEN_V01 + 1);
2792 		cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA,
2793 				       0, event_data);
2794 	} else {
2795 		if (event_data->mem_type == QMI_WLFW_MEM_QDSS_V01) {
2796 			if (!ind_msg->file_name_valid)
2797 				strlcpy(event_data->file_name, "qdss_trace_ddr",
2798 					QMI_WLFW_MAX_STR_LEN_V01 + 1);
2799 		} else {
2800 			if (!ind_msg->file_name_valid)
2801 				strlcpy(event_data->file_name, "fw_mem_dump",
2802 					QMI_WLFW_MAX_STR_LEN_V01 + 1);
2803 		}
2804 
2805 		cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE,
2806 				       0, event_data);
2807 	}
2808 
2809 	return;
2810 
2811 free_event_data:
2812 	kfree(event_data);
2813 }
2814 
2815 static void cnss_wlfw_qdss_trace_free_ind_cb(struct qmi_handle *qmi_wlfw,
2816 					     struct sockaddr_qrtr *sq,
2817 					     struct qmi_txn *txn,
2818 					     const void *data)
2819 {
2820 	struct cnss_plat_data *plat_priv =
2821 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2822 
2823 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_FREE,
2824 			       0, NULL);
2825 }
2826 
2827 static void cnss_wlfw_respond_get_info_ind_cb(struct qmi_handle *qmi_wlfw,
2828 					      struct sockaddr_qrtr *sq,
2829 					      struct qmi_txn *txn,
2830 					      const void *data)
2831 {
2832 	struct cnss_plat_data *plat_priv =
2833 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2834 	const struct wlfw_respond_get_info_ind_msg_v01 *ind_msg = data;
2835 
2836 	cnss_pr_buf("Received QMI WLFW respond get info indication\n");
2837 
2838 	if (!txn) {
2839 		cnss_pr_err("Spurious indication\n");
2840 		return;
2841 	}
2842 
2843 	cnss_pr_buf("Extract message with event length: %d, type: %d, is last: %d, seq no: %d\n",
2844 		    ind_msg->data_len, ind_msg->type,
2845 		    ind_msg->is_last, ind_msg->seq_no);
2846 
2847 	if (plat_priv->get_info_cb_ctx && plat_priv->get_info_cb)
2848 		plat_priv->get_info_cb(plat_priv->get_info_cb_ctx,
2849 				       (void *)ind_msg->data,
2850 				       ind_msg->data_len);
2851 }
2852 
2853 static int cnss_ims_wfc_call_twt_cfg_send_sync
2854 	(struct cnss_plat_data *plat_priv,
2855 	 const struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg)
2856 {
2857 	struct ims_private_service_wfc_call_twt_config_req_msg_v01 *req;
2858 	struct ims_private_service_wfc_call_twt_config_rsp_msg_v01 *resp;
2859 	struct qmi_txn txn;
2860 	int ret = 0;
2861 
2862 	if (!test_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state)) {
2863 		cnss_pr_err("Drop FW WFC indication as IMS QMI not connected\n");
2864 		return -EINVAL;
2865 	}
2866 
2867 	req = kzalloc(sizeof(*req), GFP_KERNEL);
2868 	if (!req)
2869 		return -ENOMEM;
2870 
2871 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
2872 	if (!resp) {
2873 		kfree(req);
2874 		return -ENOMEM;
2875 	}
2876 
2877 	req->twt_sta_start_valid = ind_msg->twt_sta_start_valid;
2878 	req->twt_sta_start = ind_msg->twt_sta_start;
2879 	req->twt_sta_int_valid = ind_msg->twt_sta_int_valid;
2880 	req->twt_sta_int = ind_msg->twt_sta_int;
2881 	req->twt_sta_upo_valid = ind_msg->twt_sta_upo_valid;
2882 	req->twt_sta_upo = ind_msg->twt_sta_upo;
2883 	req->twt_sta_sp_valid = ind_msg->twt_sta_sp_valid;
2884 	req->twt_sta_sp = ind_msg->twt_sta_sp;
2885 	req->twt_sta_dl_valid = req->twt_sta_dl_valid;
2886 	req->twt_sta_dl = req->twt_sta_dl;
2887 	req->twt_sta_config_changed_valid =
2888 				ind_msg->twt_sta_config_changed_valid;
2889 	req->twt_sta_config_changed = ind_msg->twt_sta_config_changed;
2890 
2891 	cnss_pr_dbg("CNSS->IMS: TWT_CFG_REQ: state: 0x%lx\n",
2892 		    plat_priv->driver_state);
2893 
2894 	ret =
2895 	qmi_txn_init(&plat_priv->ims_qmi, &txn,
2896 		     ims_private_service_wfc_call_twt_config_rsp_msg_v01_ei,
2897 		     resp);
2898 	if (ret < 0) {
2899 		cnss_pr_err("CNSS->IMS: TWT_CFG_REQ: QMI Txn Init Err: %d\n",
2900 			    ret);
2901 		goto out;
2902 	}
2903 
2904 	ret =
2905 	qmi_send_request(&plat_priv->ims_qmi, NULL, &txn,
2906 			 QMI_IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_V01,
2907 		IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_MSG_V01_MAX_MSG_LEN,
2908 		ims_private_service_wfc_call_twt_config_req_msg_v01_ei, req);
2909 	if (ret < 0) {
2910 		qmi_txn_cancel(&txn);
2911 		cnss_pr_err("CNSS->IMS: TWT_CFG_REQ: QMI Send Err: %d\n", ret);
2912 		goto out;
2913 	}
2914 
2915 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
2916 	if (ret < 0) {
2917 		cnss_pr_err("IMS->CNSS: TWT_CFG_RSP: QMI Wait Err: %d\n", ret);
2918 		goto out;
2919 	}
2920 
2921 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
2922 		cnss_pr_err("IMS->CNSS: TWT_CFG_RSP: Result: %d Err: %d\n",
2923 			    resp->resp.result, resp->resp.error);
2924 		ret = -resp->resp.result;
2925 		goto out;
2926 	}
2927 	ret = 0;
2928 out:
2929 	kfree(req);
2930 	kfree(resp);
2931 	return ret;
2932 }
2933 
2934 int cnss_process_twt_cfg_ind_event(struct cnss_plat_data *plat_priv,
2935 				   void *data)
2936 {
2937 	int ret;
2938 	struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg = data;
2939 
2940 	ret = cnss_ims_wfc_call_twt_cfg_send_sync(plat_priv, ind_msg);
2941 	kfree(data);
2942 	return ret;
2943 }
2944 
2945 static void cnss_wlfw_process_twt_cfg_ind(struct qmi_handle *qmi_wlfw,
2946 					  struct sockaddr_qrtr *sq,
2947 					  struct qmi_txn *txn,
2948 					  const void *data)
2949 {
2950 	struct cnss_plat_data *plat_priv =
2951 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
2952 	const struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg = data;
2953 	struct wlfw_wfc_call_twt_config_ind_msg_v01 *event_data;
2954 
2955 	if (!txn) {
2956 		cnss_pr_err("FW->CNSS: TWT_CFG_IND: Spurious indication\n");
2957 		return;
2958 	}
2959 
2960 	if (!ind_msg) {
2961 		cnss_pr_err("FW->CNSS: TWT_CFG_IND: Invalid indication\n");
2962 		return;
2963 	}
2964 	cnss_pr_dbg("FW->CNSS: TWT_CFG_IND: %x %llx, %x %x, %x %x, %x %x, %x %x, %x %x\n",
2965 		    ind_msg->twt_sta_start_valid, ind_msg->twt_sta_start,
2966 		    ind_msg->twt_sta_int_valid, ind_msg->twt_sta_int,
2967 		    ind_msg->twt_sta_upo_valid, ind_msg->twt_sta_upo,
2968 		    ind_msg->twt_sta_sp_valid, ind_msg->twt_sta_sp,
2969 		    ind_msg->twt_sta_dl_valid, ind_msg->twt_sta_dl,
2970 		    ind_msg->twt_sta_config_changed_valid,
2971 		    ind_msg->twt_sta_config_changed);
2972 
2973 	event_data = kmemdup(ind_msg, sizeof(*event_data), GFP_KERNEL);
2974 	if (!event_data)
2975 		return;
2976 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND, 0,
2977 			       event_data);
2978 }
2979 
2980 static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = {
2981 	{
2982 		.type = QMI_INDICATION,
2983 		.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01,
2984 		.ei = wlfw_request_mem_ind_msg_v01_ei,
2985 		.decoded_size = sizeof(struct wlfw_request_mem_ind_msg_v01),
2986 		.fn = cnss_wlfw_request_mem_ind_cb
2987 	},
2988 	{
2989 		.type = QMI_INDICATION,
2990 		.msg_id = QMI_WLFW_FW_MEM_READY_IND_V01,
2991 		.ei = wlfw_fw_mem_ready_ind_msg_v01_ei,
2992 		.decoded_size = sizeof(struct wlfw_fw_mem_ready_ind_msg_v01),
2993 		.fn = cnss_wlfw_fw_mem_ready_ind_cb
2994 	},
2995 	{
2996 		.type = QMI_INDICATION,
2997 		.msg_id = QMI_WLFW_FW_READY_IND_V01,
2998 		.ei = wlfw_fw_ready_ind_msg_v01_ei,
2999 		.decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01),
3000 		.fn = cnss_wlfw_fw_ready_ind_cb
3001 	},
3002 	{
3003 		.type = QMI_INDICATION,
3004 		.msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01,
3005 		.ei = wlfw_fw_init_done_ind_msg_v01_ei,
3006 		.decoded_size = sizeof(struct wlfw_fw_init_done_ind_msg_v01),
3007 		.fn = cnss_wlfw_fw_init_done_ind_cb
3008 	},
3009 	{
3010 		.type = QMI_INDICATION,
3011 		.msg_id = QMI_WLFW_PIN_CONNECT_RESULT_IND_V01,
3012 		.ei = wlfw_pin_connect_result_ind_msg_v01_ei,
3013 		.decoded_size =
3014 			sizeof(struct wlfw_pin_connect_result_ind_msg_v01),
3015 		.fn = cnss_wlfw_pin_result_ind_cb
3016 	},
3017 	{
3018 		.type = QMI_INDICATION,
3019 		.msg_id = QMI_WLFW_CAL_DONE_IND_V01,
3020 		.ei = wlfw_cal_done_ind_msg_v01_ei,
3021 		.decoded_size = sizeof(struct wlfw_cal_done_ind_msg_v01),
3022 		.fn = cnss_wlfw_cal_done_ind_cb
3023 	},
3024 	{
3025 		.type = QMI_INDICATION,
3026 		.msg_id = QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01,
3027 		.ei = wlfw_qdss_trace_req_mem_ind_msg_v01_ei,
3028 		.decoded_size =
3029 		sizeof(struct wlfw_qdss_trace_req_mem_ind_msg_v01),
3030 		.fn = cnss_wlfw_qdss_trace_req_mem_ind_cb
3031 	},
3032 	{
3033 		.type = QMI_INDICATION,
3034 		.msg_id = QMI_WLFW_QDSS_TRACE_SAVE_IND_V01,
3035 		.ei = wlfw_qdss_trace_save_ind_msg_v01_ei,
3036 		.decoded_size =
3037 		sizeof(struct wlfw_qdss_trace_save_ind_msg_v01),
3038 		.fn = cnss_wlfw_fw_mem_file_save_ind_cb
3039 	},
3040 	{
3041 		.type = QMI_INDICATION,
3042 		.msg_id = QMI_WLFW_QDSS_TRACE_FREE_IND_V01,
3043 		.ei = wlfw_qdss_trace_free_ind_msg_v01_ei,
3044 		.decoded_size =
3045 		sizeof(struct wlfw_qdss_trace_free_ind_msg_v01),
3046 		.fn = cnss_wlfw_qdss_trace_free_ind_cb
3047 	},
3048 	{
3049 		.type = QMI_INDICATION,
3050 		.msg_id = QMI_WLFW_RESPOND_GET_INFO_IND_V01,
3051 		.ei = wlfw_respond_get_info_ind_msg_v01_ei,
3052 		.decoded_size =
3053 		sizeof(struct wlfw_respond_get_info_ind_msg_v01),
3054 		.fn = cnss_wlfw_respond_get_info_ind_cb
3055 	},
3056 	{
3057 		.type = QMI_INDICATION,
3058 		.msg_id = QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01,
3059 		.ei = wlfw_wfc_call_twt_config_ind_msg_v01_ei,
3060 		.decoded_size =
3061 		sizeof(struct wlfw_wfc_call_twt_config_ind_msg_v01),
3062 		.fn = cnss_wlfw_process_twt_cfg_ind
3063 	},
3064 	{}
3065 };
3066 
3067 static int cnss_wlfw_connect_to_server(struct cnss_plat_data *plat_priv,
3068 				       void *data)
3069 {
3070 	struct cnss_qmi_event_server_arrive_data *event_data = data;
3071 	struct qmi_handle *qmi_wlfw = &plat_priv->qmi_wlfw;
3072 	struct sockaddr_qrtr sq = { 0 };
3073 	int ret = 0;
3074 
3075 	if (!event_data)
3076 		return -EINVAL;
3077 
3078 	sq.sq_family = AF_QIPCRTR;
3079 	sq.sq_node = event_data->node;
3080 	sq.sq_port = event_data->port;
3081 
3082 	ret = kernel_connect(qmi_wlfw->sock, (struct sockaddr *)&sq,
3083 			     sizeof(sq), 0);
3084 	if (ret < 0) {
3085 		cnss_pr_err("Failed to connect to QMI WLFW remote service port\n");
3086 		goto out;
3087 	}
3088 
3089 	set_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state);
3090 
3091 	cnss_pr_info("QMI WLFW service connected, state: 0x%lx\n",
3092 		     plat_priv->driver_state);
3093 
3094 	kfree(data);
3095 	return 0;
3096 
3097 out:
3098 	CNSS_QMI_ASSERT();
3099 	kfree(data);
3100 	return ret;
3101 }
3102 
3103 int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data)
3104 {
3105 	int ret = 0;
3106 
3107 	if (!plat_priv)
3108 		return -ENODEV;
3109 
3110 	if (test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state)) {
3111 		cnss_pr_err("Unexpected WLFW server arrive\n");
3112 		CNSS_ASSERT(0);
3113 		return -EINVAL;
3114 	}
3115 
3116 	cnss_ignore_qmi_failure(false);
3117 
3118 	ret = cnss_wlfw_connect_to_server(plat_priv, data);
3119 	if (ret < 0)
3120 		goto out;
3121 
3122 	ret = cnss_wlfw_ind_register_send_sync(plat_priv);
3123 	if (ret < 0) {
3124 		if (ret == -EALREADY)
3125 			ret = 0;
3126 		goto out;
3127 	}
3128 
3129 	ret = cnss_wlfw_host_cap_send_sync(plat_priv);
3130 	if (ret < 0)
3131 		goto out;
3132 
3133 	return 0;
3134 
3135 out:
3136 	return ret;
3137 }
3138 
3139 int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
3140 {
3141 	int ret;
3142 
3143 	if (!plat_priv)
3144 		return -ENODEV;
3145 
3146 	clear_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state);
3147 
3148 	cnss_pr_info("QMI WLFW service disconnected, state: 0x%lx\n",
3149 		     plat_priv->driver_state);
3150 
3151 	cnss_qmi_deinit(plat_priv);
3152 
3153 	clear_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state);
3154 
3155 	ret = cnss_qmi_init(plat_priv);
3156 	if (ret < 0) {
3157 		cnss_pr_err("QMI WLFW service registraton failed, ret\n", ret);
3158 		CNSS_ASSERT(0);
3159 	}
3160 	return 0;
3161 }
3162 
3163 static int wlfw_new_server(struct qmi_handle *qmi_wlfw,
3164 			   struct qmi_service *service)
3165 {
3166 	struct cnss_plat_data *plat_priv =
3167 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
3168 	struct cnss_qmi_event_server_arrive_data *event_data;
3169 
3170 	if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) {
3171 		cnss_pr_info("WLFW server delete in progress, Ignore server arrive, state: 0x%lx\n",
3172 			     plat_priv->driver_state);
3173 		return 0;
3174 	}
3175 
3176 	cnss_pr_dbg("WLFW server arriving: node %u port %u\n",
3177 		    service->node, service->port);
3178 
3179 	event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
3180 	if (!event_data)
3181 		return -ENOMEM;
3182 
3183 	event_data->node = service->node;
3184 	event_data->port = service->port;
3185 
3186 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_SERVER_ARRIVE,
3187 			       0, event_data);
3188 
3189 	return 0;
3190 }
3191 
3192 static void wlfw_del_server(struct qmi_handle *qmi_wlfw,
3193 			    struct qmi_service *service)
3194 {
3195 	struct cnss_plat_data *plat_priv =
3196 		container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw);
3197 
3198 	if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) {
3199 		cnss_pr_info("WLFW server delete in progress, Ignore server delete, state: 0x%lx\n",
3200 			     plat_priv->driver_state);
3201 		return;
3202 	}
3203 
3204 	cnss_pr_dbg("WLFW server exiting\n");
3205 
3206 	if (plat_priv) {
3207 		cnss_ignore_qmi_failure(true);
3208 		set_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state);
3209 	}
3210 
3211 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_SERVER_EXIT,
3212 			       0, NULL);
3213 }
3214 
3215 static struct qmi_ops qmi_wlfw_ops = {
3216 	.new_server = wlfw_new_server,
3217 	.del_server = wlfw_del_server,
3218 };
3219 
3220 int cnss_qmi_init(struct cnss_plat_data *plat_priv)
3221 {
3222 	int ret = 0;
3223 
3224 	ret = qmi_handle_init(&plat_priv->qmi_wlfw,
3225 			      QMI_WLFW_MAX_RECV_BUF_SIZE,
3226 			      &qmi_wlfw_ops, qmi_wlfw_msg_handlers);
3227 	if (ret < 0) {
3228 		cnss_pr_err("Failed to initialize WLFW QMI handle, err: %d\n",
3229 			    ret);
3230 		goto out;
3231 	}
3232 
3233 	ret = qmi_add_lookup(&plat_priv->qmi_wlfw, WLFW_SERVICE_ID_V01,
3234 			     WLFW_SERVICE_VERS_V01, WLFW_SERVICE_INS_ID_V01);
3235 	if (ret < 0)
3236 		cnss_pr_err("Failed to add WLFW QMI lookup, err: %d\n", ret);
3237 
3238 out:
3239 	return ret;
3240 }
3241 
3242 void cnss_qmi_deinit(struct cnss_plat_data *plat_priv)
3243 {
3244 	qmi_handle_release(&plat_priv->qmi_wlfw);
3245 }
3246 
3247 int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv)
3248 {
3249 	struct dms_get_mac_address_req_msg_v01 req;
3250 	struct dms_get_mac_address_resp_msg_v01 resp;
3251 	struct qmi_txn txn;
3252 	int ret = 0;
3253 
3254 	if  (!test_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state)) {
3255 		cnss_pr_err("DMS QMI connection not established\n");
3256 		return -EINVAL;
3257 	}
3258 	cnss_pr_dbg("Requesting DMS MAC address");
3259 
3260 	memset(&resp, 0, sizeof(resp));
3261 	ret = qmi_txn_init(&plat_priv->qmi_dms, &txn,
3262 			   dms_get_mac_address_resp_msg_v01_ei, &resp);
3263 	if (ret < 0) {
3264 		cnss_pr_err("Failed to initialize txn for dms, err: %d\n",
3265 			    ret);
3266 		goto out;
3267 	}
3268 	req.device = DMS_DEVICE_MAC_WLAN_V01;
3269 	ret = qmi_send_request(&plat_priv->qmi_dms, NULL, &txn,
3270 			       QMI_DMS_GET_MAC_ADDRESS_REQ_V01,
3271 			       DMS_GET_MAC_ADDRESS_REQ_MSG_V01_MAX_MSG_LEN,
3272 			       dms_get_mac_address_req_msg_v01_ei, &req);
3273 	if (ret < 0) {
3274 		qmi_txn_cancel(&txn);
3275 		cnss_pr_err("Failed to send QMI_DMS_GET_MAC_ADDRESS_REQ_V01, err: %d\n",
3276 			    ret);
3277 		goto out;
3278 	}
3279 	ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF);
3280 	if (ret < 0) {
3281 		cnss_pr_err("Failed to wait for QMI_DMS_GET_MAC_ADDRESS_RESP_V01, err: %d\n",
3282 			    ret);
3283 		goto out;
3284 	}
3285 
3286 	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
3287 		cnss_pr_err("QMI_DMS_GET_MAC_ADDRESS_REQ_V01 failed, result: %d, err: %d\n",
3288 			    resp.resp.result, resp.resp.error);
3289 		ret = -resp.resp.result;
3290 		goto out;
3291 	}
3292 	if (!resp.mac_address_valid ||
3293 	    resp.mac_address_len != QMI_WLFW_MAC_ADDR_SIZE_V01) {
3294 		cnss_pr_err("Invalid MAC address received from DMS\n");
3295 		plat_priv->dms.mac_valid = false;
3296 		goto out;
3297 	}
3298 	plat_priv->dms.mac_valid = true;
3299 	memcpy(plat_priv->dms.mac, resp.mac_address, QMI_WLFW_MAC_ADDR_SIZE_V01);
3300 	cnss_pr_info("Received DMS MAC: [%pM]\n", plat_priv->dms.mac);
3301 out:
3302 	return ret;
3303 }
3304 
3305 static int cnss_dms_connect_to_server(struct cnss_plat_data *plat_priv,
3306 				      unsigned int node, unsigned int port)
3307 {
3308 	struct qmi_handle *qmi_dms = &plat_priv->qmi_dms;
3309 	struct sockaddr_qrtr sq = {0};
3310 	int ret = 0;
3311 
3312 	sq.sq_family = AF_QIPCRTR;
3313 	sq.sq_node = node;
3314 	sq.sq_port = port;
3315 
3316 	ret = kernel_connect(qmi_dms->sock, (struct sockaddr *)&sq,
3317 			     sizeof(sq), 0);
3318 	if (ret < 0) {
3319 		cnss_pr_err("Failed to connect to QMI DMS remote service Node: %d Port: %d\n",
3320 			    node, port);
3321 		goto out;
3322 	}
3323 
3324 	set_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state);
3325 	cnss_pr_info("QMI DMS service connected, state: 0x%lx\n",
3326 		     plat_priv->driver_state);
3327 out:
3328 	return ret;
3329 }
3330 
3331 static int dms_new_server(struct qmi_handle *qmi_dms,
3332 			  struct qmi_service *service)
3333 {
3334 	struct cnss_plat_data *plat_priv =
3335 		container_of(qmi_dms, struct cnss_plat_data, qmi_dms);
3336 
3337 	if (!service)
3338 		return -EINVAL;
3339 
3340 	return cnss_dms_connect_to_server(plat_priv, service->node,
3341 					  service->port);
3342 }
3343 
3344 static void cnss_dms_server_exit_work(struct work_struct *work)
3345 {
3346 	int ret;
3347 	struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
3348 
3349 	cnss_dms_deinit(plat_priv);
3350 
3351 	cnss_pr_info("QMI DMS Server Exit");
3352 	clear_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
3353 
3354 	ret = cnss_dms_init(plat_priv);
3355 	if (ret < 0)
3356 		cnss_pr_err("QMI DMS service registraton failed, ret\n", ret);
3357 }
3358 
3359 static DECLARE_WORK(cnss_dms_del_work, cnss_dms_server_exit_work);
3360 
3361 static void dms_del_server(struct qmi_handle *qmi_dms,
3362 			   struct qmi_service *service)
3363 {
3364 	struct cnss_plat_data *plat_priv =
3365 		container_of(qmi_dms, struct cnss_plat_data, qmi_dms);
3366 
3367 	if (!plat_priv)
3368 		return;
3369 
3370 	if (test_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state)) {
3371 		cnss_pr_info("DMS server delete or cnss remove in progress, Ignore server delete: 0x%lx\n",
3372 			     plat_priv->driver_state);
3373 		return;
3374 	}
3375 
3376 	set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
3377 	clear_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state);
3378 	cnss_pr_info("QMI DMS service disconnected, state: 0x%lx\n",
3379 		     plat_priv->driver_state);
3380 	schedule_work(&cnss_dms_del_work);
3381 }
3382 
3383 void cnss_cancel_dms_work(void)
3384 {
3385 	cancel_work_sync(&cnss_dms_del_work);
3386 }
3387 
3388 static struct qmi_ops qmi_dms_ops = {
3389 	.new_server = dms_new_server,
3390 	.del_server = dms_del_server,
3391 };
3392 
3393 int cnss_dms_init(struct cnss_plat_data *plat_priv)
3394 {
3395 	int ret = 0;
3396 
3397 	ret = qmi_handle_init(&plat_priv->qmi_dms, DMS_QMI_MAX_MSG_LEN,
3398 			      &qmi_dms_ops, NULL);
3399 	if (ret < 0) {
3400 		cnss_pr_err("Failed to initialize DMS handle, err: %d\n", ret);
3401 		goto out;
3402 	}
3403 
3404 	ret = qmi_add_lookup(&plat_priv->qmi_dms, DMS_SERVICE_ID_V01,
3405 			     DMS_SERVICE_VERS_V01, 0);
3406 	if (ret < 0)
3407 		cnss_pr_err("Failed to add DMS lookup, err: %d\n", ret);
3408 out:
3409 	return ret;
3410 }
3411 
3412 void cnss_dms_deinit(struct cnss_plat_data *plat_priv)
3413 {
3414 	set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state);
3415 	qmi_handle_release(&plat_priv->qmi_dms);
3416 }
3417 
3418 int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv)
3419 {
3420 	int ret;
3421 	struct coex_antenna_switch_to_wlan_req_msg_v01 *req;
3422 	struct coex_antenna_switch_to_wlan_resp_msg_v01 *resp;
3423 	struct qmi_txn txn;
3424 
3425 	if (!plat_priv)
3426 		return -ENODEV;
3427 
3428 	cnss_pr_dbg("Sending coex antenna switch_to_wlan\n");
3429 
3430 	req = kzalloc(sizeof(*req), GFP_KERNEL);
3431 	if (!req)
3432 		return -ENOMEM;
3433 
3434 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
3435 	if (!resp) {
3436 		kfree(req);
3437 		return -ENOMEM;
3438 	}
3439 
3440 	req->antenna = plat_priv->antenna;
3441 
3442 	ret = qmi_txn_init(&plat_priv->coex_qmi, &txn,
3443 			   coex_antenna_switch_to_wlan_resp_msg_v01_ei, resp);
3444 	if (ret < 0) {
3445 		cnss_pr_err("Fail to init txn for coex antenna switch_to_wlan resp %d\n",
3446 			    ret);
3447 		goto out;
3448 	}
3449 
3450 	ret = qmi_send_request
3451 		(&plat_priv->coex_qmi, NULL, &txn,
3452 		 QMI_COEX_SWITCH_ANTENNA_TO_WLAN_REQ_V01,
3453 		 COEX_ANTENNA_SWITCH_TO_WLAN_REQ_MSG_V01_MAX_MSG_LEN,
3454 		 coex_antenna_switch_to_wlan_req_msg_v01_ei, req);
3455 	if (ret < 0) {
3456 		qmi_txn_cancel(&txn);
3457 		cnss_pr_err("Fail to send coex antenna switch_to_wlan req %d\n",
3458 			    ret);
3459 		goto out;
3460 	}
3461 
3462 	ret = qmi_txn_wait(&txn, COEX_TIMEOUT);
3463 	if (ret < 0) {
3464 		cnss_pr_err("Coex antenna switch_to_wlan resp wait failed with ret %d\n",
3465 			    ret);
3466 		goto out;
3467 	} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
3468 		cnss_pr_err("Coex antenna switch_to_wlan request rejected, result:%d error:%d\n",
3469 			    resp->resp.result, resp->resp.error);
3470 		ret = -resp->resp.result;
3471 		goto out;
3472 	}
3473 
3474 	if (resp->grant_valid)
3475 		plat_priv->grant = resp->grant;
3476 
3477 	cnss_pr_dbg("Coex antenna grant: 0x%llx\n", resp->grant);
3478 
3479 	kfree(resp);
3480 	kfree(req);
3481 	return 0;
3482 
3483 out:
3484 	kfree(resp);
3485 	kfree(req);
3486 	return ret;
3487 }
3488 
3489 int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv)
3490 {
3491 	int ret;
3492 	struct coex_antenna_switch_to_mdm_req_msg_v01 *req;
3493 	struct coex_antenna_switch_to_mdm_resp_msg_v01 *resp;
3494 	struct qmi_txn txn;
3495 
3496 	if (!plat_priv)
3497 		return -ENODEV;
3498 
3499 	cnss_pr_dbg("Sending coex antenna switch_to_mdm\n");
3500 
3501 	req = kzalloc(sizeof(*req), GFP_KERNEL);
3502 	if (!req)
3503 		return -ENOMEM;
3504 
3505 	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
3506 	if (!resp) {
3507 		kfree(req);
3508 		return -ENOMEM;
3509 	}
3510 
3511 	req->antenna = plat_priv->antenna;
3512 
3513 	ret = qmi_txn_init(&plat_priv->coex_qmi, &txn,
3514 			   coex_antenna_switch_to_mdm_resp_msg_v01_ei, resp);
3515 	if (ret < 0) {
3516 		cnss_pr_err("Fail to init txn for coex antenna switch_to_mdm resp %d\n",
3517 			    ret);
3518 		goto out;
3519 	}
3520 
3521 	ret = qmi_send_request
3522 		(&plat_priv->coex_qmi, NULL, &txn,
3523 		 QMI_COEX_SWITCH_ANTENNA_TO_MDM_REQ_V01,
3524 		 COEX_ANTENNA_SWITCH_TO_MDM_REQ_MSG_V01_MAX_MSG_LEN,
3525 		 coex_antenna_switch_to_mdm_req_msg_v01_ei, req);
3526 	if (ret < 0) {
3527 		qmi_txn_cancel(&txn);
3528 		cnss_pr_err("Fail to send coex antenna switch_to_mdm req %d\n",
3529 			    ret);
3530 		goto out;
3531 	}
3532 
3533 	ret = qmi_txn_wait(&txn, COEX_TIMEOUT);
3534 	if (ret < 0) {
3535 		cnss_pr_err("Coex antenna switch_to_mdm resp wait failed with ret %d\n",
3536 			    ret);
3537 		goto out;
3538 	} else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
3539 		cnss_pr_err("Coex antenna switch_to_mdm request rejected, result:%d error:%d\n",
3540 			    resp->resp.result, resp->resp.error);
3541 		ret = -resp->resp.result;
3542 		goto out;
3543 	}
3544 
3545 	kfree(resp);
3546 	kfree(req);
3547 	return 0;
3548 
3549 out:
3550 	kfree(resp);
3551 	kfree(req);
3552 	return ret;
3553 }
3554 
3555 int cnss_send_subsys_restart_level_msg(struct cnss_plat_data *plat_priv)
3556 {
3557 	int ret;
3558 	struct wlfw_subsys_restart_level_req_msg_v01 req;
3559 	struct wlfw_subsys_restart_level_resp_msg_v01 resp;
3560 	u8 pcss_enabled;
3561 
3562 	if (!plat_priv)
3563 		return -ENODEV;
3564 
3565 	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
3566 		cnss_pr_dbg("Can't send pcss cmd before fw ready\n");
3567 		return 0;
3568 	}
3569 
3570 	pcss_enabled = plat_priv->recovery_pcss_enabled;
3571 	cnss_pr_dbg("Sending pcss recovery status: %d\n", pcss_enabled);
3572 
3573 	req.restart_level_type_valid = 1;
3574 	req.restart_level_type = pcss_enabled;
3575 
3576 	ret = qmi_send_wait(&plat_priv->qmi_wlfw, &req, &resp,
3577 			    wlfw_subsys_restart_level_req_msg_v01_ei,
3578 			    wlfw_subsys_restart_level_resp_msg_v01_ei,
3579 			    QMI_WLFW_SUBSYS_RESTART_LEVEL_REQ_V01,
3580 			    WLFW_SUBSYS_RESTART_LEVEL_REQ_MSG_V01_MAX_MSG_LEN,
3581 			    QMI_WLFW_TIMEOUT_JF);
3582 
3583 	if (ret < 0)
3584 		cnss_pr_err("pcss recovery setting failed with ret %d\n", ret);
3585 	return ret;
3586 }
3587 
3588 static int coex_new_server(struct qmi_handle *qmi,
3589 			   struct qmi_service *service)
3590 {
3591 	struct cnss_plat_data *plat_priv =
3592 		container_of(qmi, struct cnss_plat_data, coex_qmi);
3593 	struct sockaddr_qrtr sq = { 0 };
3594 	int ret = 0;
3595 
3596 	cnss_pr_dbg("COEX server arrive: node %u port %u\n",
3597 		    service->node, service->port);
3598 
3599 	sq.sq_family = AF_QIPCRTR;
3600 	sq.sq_node = service->node;
3601 	sq.sq_port = service->port;
3602 	ret = kernel_connect(qmi->sock, (struct sockaddr *)&sq, sizeof(sq), 0);
3603 	if (ret < 0) {
3604 		cnss_pr_err("Fail to connect to remote service port\n");
3605 		return ret;
3606 	}
3607 
3608 	set_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state);
3609 	cnss_pr_dbg("COEX Server Connected: 0x%lx\n",
3610 		    plat_priv->driver_state);
3611 	return 0;
3612 }
3613 
3614 static void coex_del_server(struct qmi_handle *qmi,
3615 			    struct qmi_service *service)
3616 {
3617 	struct cnss_plat_data *plat_priv =
3618 		container_of(qmi, struct cnss_plat_data, coex_qmi);
3619 
3620 	cnss_pr_dbg("COEX server exit\n");
3621 
3622 	clear_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state);
3623 }
3624 
3625 static struct qmi_ops coex_qmi_ops = {
3626 	.new_server = coex_new_server,
3627 	.del_server = coex_del_server,
3628 };
3629 
3630 int cnss_register_coex_service(struct cnss_plat_data *plat_priv)
3631 {	int ret;
3632 
3633 	ret = qmi_handle_init(&plat_priv->coex_qmi,
3634 			      COEX_SERVICE_MAX_MSG_LEN,
3635 			      &coex_qmi_ops, NULL);
3636 	if (ret < 0)
3637 		return ret;
3638 
3639 	ret = qmi_add_lookup(&plat_priv->coex_qmi, COEX_SERVICE_ID_V01,
3640 			     COEX_SERVICE_VERS_V01, 0);
3641 	return ret;
3642 }
3643 
3644 void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv)
3645 {
3646 	qmi_handle_release(&plat_priv->coex_qmi);
3647 }
3648 
3649 /* IMS Service */
3650 int ims_subscribe_for_indication_send_async(struct cnss_plat_data *plat_priv)
3651 {
3652 	int ret;
3653 	struct ims_private_service_subscribe_for_indications_req_msg_v01 *req;
3654 	struct qmi_txn *txn;
3655 
3656 	if (!plat_priv)
3657 		return -ENODEV;
3658 
3659 	cnss_pr_dbg("Sending ASYNC ims subscribe for indication\n");
3660 
3661 	req = kzalloc(sizeof(*req), GFP_KERNEL);
3662 	if (!req)
3663 		return -ENOMEM;
3664 
3665 	req->wfc_call_status_valid = 1;
3666 	req->wfc_call_status = 1;
3667 
3668 	txn = &plat_priv->txn;
3669 	ret = qmi_txn_init(&plat_priv->ims_qmi, txn, NULL, NULL);
3670 	if (ret < 0) {
3671 		cnss_pr_err("Fail to init txn for ims subscribe for indication resp %d\n",
3672 			    ret);
3673 		goto out;
3674 	}
3675 
3676 	ret = qmi_send_request
3677 	(&plat_priv->ims_qmi, NULL, txn,
3678 	QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01,
3679 	IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_MSG_V01_MAX_MSG_LEN,
3680 	ims_private_service_subscribe_for_indications_req_msg_v01_ei, req);
3681 	if (ret < 0) {
3682 		qmi_txn_cancel(txn);
3683 		cnss_pr_err("Fail to send ims subscribe for indication req %d\n",
3684 			    ret);
3685 		goto out;
3686 	}
3687 
3688 	kfree(req);
3689 	return 0;
3690 
3691 out:
3692 	kfree(req);
3693 	return ret;
3694 }
3695 
3696 static void ims_subscribe_for_indication_resp_cb(struct qmi_handle *qmi,
3697 						 struct sockaddr_qrtr *sq,
3698 						 struct qmi_txn *txn,
3699 						 const void *data)
3700 {
3701 	const
3702 	struct ims_private_service_subscribe_for_indications_rsp_msg_v01 *resp =
3703 		data;
3704 
3705 	cnss_pr_dbg("Received IMS subscribe indication response\n");
3706 
3707 	if (!txn) {
3708 		cnss_pr_err("spurious response\n");
3709 		return;
3710 	}
3711 
3712 	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
3713 		cnss_pr_err("IMS subscribe for indication request rejected, result:%d error:%d\n",
3714 			    resp->resp.result, resp->resp.error);
3715 		txn->result = -resp->resp.result;
3716 	}
3717 }
3718 
3719 int cnss_process_wfc_call_ind_event(struct cnss_plat_data *plat_priv,
3720 				    void *data)
3721 {
3722 	int ret;
3723 	struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg = data;
3724 
3725 	ret = cnss_wlfw_wfc_call_status_send_sync(plat_priv, ind_msg);
3726 	kfree(data);
3727 	return ret;
3728 }
3729 
3730 static void
3731 cnss_ims_process_wfc_call_ind_cb(struct qmi_handle *ims_qmi,
3732 				 struct sockaddr_qrtr *sq,
3733 				 struct qmi_txn *txn, const void *data)
3734 {
3735 	struct cnss_plat_data *plat_priv =
3736 		container_of(ims_qmi, struct cnss_plat_data, ims_qmi);
3737 	const
3738 	struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg = data;
3739 	struct ims_private_service_wfc_call_status_ind_msg_v01 *event_data;
3740 
3741 	if (!txn) {
3742 		cnss_pr_err("IMS->CNSS: WFC_CALL_IND: Spurious indication\n");
3743 		return;
3744 	}
3745 
3746 	if (!ind_msg) {
3747 		cnss_pr_err("IMS->CNSS: WFC_CALL_IND: Invalid indication\n");
3748 		return;
3749 	}
3750 	cnss_pr_dbg("IMS->CNSS: WFC_CALL_IND: %x, %x %x, %x %x, %x %llx, %x %x, %x %x\n",
3751 		    ind_msg->wfc_call_active, ind_msg->all_wfc_calls_held_valid,
3752 		    ind_msg->all_wfc_calls_held,
3753 		    ind_msg->is_wfc_emergency_valid, ind_msg->is_wfc_emergency,
3754 		    ind_msg->twt_ims_start_valid, ind_msg->twt_ims_start,
3755 		    ind_msg->twt_ims_int_valid, ind_msg->twt_ims_int,
3756 		    ind_msg->media_quality_valid, ind_msg->media_quality);
3757 
3758 	event_data = kmemdup(ind_msg, sizeof(*event_data), GFP_KERNEL);
3759 	if (!event_data)
3760 		return;
3761 	cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND,
3762 			       0, event_data);
3763 }
3764 
3765 static struct qmi_msg_handler qmi_ims_msg_handlers[] = {
3766 	{
3767 		.type = QMI_RESPONSE,
3768 		.msg_id =
3769 		QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01,
3770 		.ei =
3771 		ims_private_service_subscribe_for_indications_rsp_msg_v01_ei,
3772 		.decoded_size = sizeof(struct
3773 		ims_private_service_subscribe_for_indications_rsp_msg_v01),
3774 		.fn = ims_subscribe_for_indication_resp_cb
3775 	},
3776 	{
3777 		.type = QMI_INDICATION,
3778 		.msg_id = QMI_IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_V01,
3779 		.ei = ims_private_service_wfc_call_status_ind_msg_v01_ei,
3780 		.decoded_size =
3781 		sizeof(struct ims_private_service_wfc_call_status_ind_msg_v01),
3782 		.fn = cnss_ims_process_wfc_call_ind_cb
3783 	},
3784 	{}
3785 };
3786 
3787 static int ims_new_server(struct qmi_handle *qmi,
3788 			  struct qmi_service *service)
3789 {
3790 	struct cnss_plat_data *plat_priv =
3791 		container_of(qmi, struct cnss_plat_data, ims_qmi);
3792 	struct sockaddr_qrtr sq = { 0 };
3793 	int ret = 0;
3794 
3795 	cnss_pr_dbg("IMS server arrive: node %u port %u\n",
3796 		    service->node, service->port);
3797 
3798 	sq.sq_family = AF_QIPCRTR;
3799 	sq.sq_node = service->node;
3800 	sq.sq_port = service->port;
3801 	ret = kernel_connect(qmi->sock, (struct sockaddr *)&sq, sizeof(sq), 0);
3802 	if (ret < 0) {
3803 		cnss_pr_err("Fail to connect to remote service port\n");
3804 		return ret;
3805 	}
3806 
3807 	set_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state);
3808 	cnss_pr_dbg("IMS Server Connected: 0x%lx\n",
3809 		    plat_priv->driver_state);
3810 
3811 	ret = ims_subscribe_for_indication_send_async(plat_priv);
3812 	return ret;
3813 }
3814 
3815 static void ims_del_server(struct qmi_handle *qmi,
3816 			   struct qmi_service *service)
3817 {
3818 	struct cnss_plat_data *plat_priv =
3819 		container_of(qmi, struct cnss_plat_data, ims_qmi);
3820 
3821 	cnss_pr_dbg("IMS server exit\n");
3822 
3823 	clear_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state);
3824 }
3825 
3826 static struct qmi_ops ims_qmi_ops = {
3827 	.new_server = ims_new_server,
3828 	.del_server = ims_del_server,
3829 };
3830 
3831 int cnss_register_ims_service(struct cnss_plat_data *plat_priv)
3832 {	int ret;
3833 
3834 	ret = qmi_handle_init(&plat_priv->ims_qmi,
3835 			      IMSPRIVATE_SERVICE_MAX_MSG_LEN,
3836 			      &ims_qmi_ops, qmi_ims_msg_handlers);
3837 	if (ret < 0)
3838 		return ret;
3839 
3840 	ret = qmi_add_lookup(&plat_priv->ims_qmi, IMSPRIVATE_SERVICE_ID_V01,
3841 			     IMSPRIVATE_SERVICE_VERS_V01, 0);
3842 	return ret;
3843 }
3844 
3845 void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv)
3846 {
3847 	qmi_handle_release(&plat_priv->ims_qmi);
3848 }
3849