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