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