1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4  */
5 
6 #include <linux/module.h>
7 #include <linux/slab.h>
8 #include <linux/remoteproc.h>
9 #include <linux/firmware.h>
10 #include <linux/of.h>
11 #include "core.h"
12 #include "dp_tx.h"
13 #include "dp_rx.h"
14 #include "debug.h"
15 #include "hif.h"
16 #include "wow.h"
17 
18 unsigned int ath11k_debug_mask;
19 EXPORT_SYMBOL(ath11k_debug_mask);
20 module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
21 MODULE_PARM_DESC(debug_mask, "Debugging mask");
22 
23 static unsigned int ath11k_crypto_mode;
24 module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);
25 MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
26 
27 /* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
28 unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
29 module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
30 MODULE_PARM_DESC(frame_mode,
31 		 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
32 
33 static const struct ath11k_hw_params ath11k_hw_params[] = {
34 	{
35 		.hw_rev = ATH11K_HW_IPQ8074,
36 		.name = "ipq8074 hw2.0",
37 		.fw = {
38 			.dir = "IPQ8074/hw2.0",
39 			.board_size = 256 * 1024,
40 			.cal_offset = 128 * 1024,
41 		},
42 		.max_radios = 3,
43 		.bdf_addr = 0x4B0C0000,
44 		.hw_ops = &ipq8074_ops,
45 		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
46 		.internal_sleep_clock = false,
47 		.regs = &ipq8074_regs,
48 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
49 		.host_ce_config = ath11k_host_ce_config_ipq8074,
50 		.ce_count = 12,
51 		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
52 		.target_ce_count = 11,
53 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
54 		.svc_to_ce_map_len = 21,
55 		.rfkill_pin = 0,
56 		.rfkill_cfg = 0,
57 		.rfkill_on_level = 0,
58 		.single_pdev_only = false,
59 		.rxdma1_enable = true,
60 		.num_rxmda_per_pdev = 1,
61 		.rx_mac_buf_ring = false,
62 		.vdev_start_delay = false,
63 		.htt_peer_map_v2 = true,
64 
65 		.spectral = {
66 			.fft_sz = 2,
67 			/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes.
68 			 * so added pad size as 2 bytes to compensate the BIN size
69 			 */
70 			.fft_pad_sz = 2,
71 			.summary_pad_sz = 0,
72 			.fft_hdr_len = 16,
73 			.max_fft_bins = 512,
74 		},
75 
76 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
77 					BIT(NL80211_IFTYPE_AP) |
78 					BIT(NL80211_IFTYPE_MESH_POINT),
79 		.supports_monitor = true,
80 		.full_monitor_mode = false,
81 		.supports_shadow_regs = false,
82 		.idle_ps = false,
83 		.supports_sta_ps = false,
84 		.cold_boot_calib = true,
85 		.fw_mem_mode = 0,
86 		.num_vdevs = 16 + 1,
87 		.num_peers = 512,
88 		.supports_suspend = false,
89 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
90 		.supports_regdb = false,
91 		.fix_l1ss = true,
92 		.credit_flow = false,
93 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
94 		.hal_params = &ath11k_hw_hal_params_ipq8074,
95 		.supports_dynamic_smps_6ghz = false,
96 		.alloc_cacheable_memory = true,
97 		.wakeup_mhi = false,
98 		.supports_rssi_stats = false,
99 		.fw_wmi_diag_event = false,
100 	},
101 	{
102 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
103 		.name = "ipq6018 hw1.0",
104 		.fw = {
105 			.dir = "IPQ6018/hw1.0",
106 			.board_size = 256 * 1024,
107 			.cal_offset = 128 * 1024,
108 		},
109 		.max_radios = 2,
110 		.bdf_addr = 0x4ABC0000,
111 		.hw_ops = &ipq6018_ops,
112 		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
113 		.internal_sleep_clock = false,
114 		.regs = &ipq8074_regs,
115 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
116 		.host_ce_config = ath11k_host_ce_config_ipq8074,
117 		.ce_count = 12,
118 		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
119 		.target_ce_count = 11,
120 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
121 		.svc_to_ce_map_len = 19,
122 		.rfkill_pin = 0,
123 		.rfkill_cfg = 0,
124 		.rfkill_on_level = 0,
125 		.single_pdev_only = false,
126 		.rxdma1_enable = true,
127 		.num_rxmda_per_pdev = 1,
128 		.rx_mac_buf_ring = false,
129 		.vdev_start_delay = false,
130 		.htt_peer_map_v2 = true,
131 
132 		.spectral = {
133 			.fft_sz = 4,
134 			.fft_pad_sz = 0,
135 			.summary_pad_sz = 0,
136 			.fft_hdr_len = 16,
137 			.max_fft_bins = 512,
138 		},
139 
140 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
141 					BIT(NL80211_IFTYPE_AP) |
142 					BIT(NL80211_IFTYPE_MESH_POINT),
143 		.supports_monitor = true,
144 		.full_monitor_mode = false,
145 		.supports_shadow_regs = false,
146 		.idle_ps = false,
147 		.supports_sta_ps = false,
148 		.cold_boot_calib = true,
149 		.fw_mem_mode = 0,
150 		.num_vdevs = 16 + 1,
151 		.num_peers = 512,
152 		.supports_suspend = false,
153 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
154 		.supports_regdb = false,
155 		.fix_l1ss = true,
156 		.credit_flow = false,
157 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
158 		.hal_params = &ath11k_hw_hal_params_ipq8074,
159 		.supports_dynamic_smps_6ghz = false,
160 		.alloc_cacheable_memory = true,
161 		.wakeup_mhi = false,
162 		.supports_rssi_stats = false,
163 		.fw_wmi_diag_event = false,
164 	},
165 	{
166 		.name = "qca6390 hw2.0",
167 		.hw_rev = ATH11K_HW_QCA6390_HW20,
168 		.fw = {
169 			.dir = "QCA6390/hw2.0",
170 			.board_size = 256 * 1024,
171 			.cal_offset = 128 * 1024,
172 		},
173 		.max_radios = 3,
174 		.bdf_addr = 0x4B0C0000,
175 		.hw_ops = &qca6390_ops,
176 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
177 		.internal_sleep_clock = true,
178 		.regs = &qca6390_regs,
179 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
180 		.host_ce_config = ath11k_host_ce_config_qca6390,
181 		.ce_count = 9,
182 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
183 		.target_ce_count = 9,
184 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
185 		.svc_to_ce_map_len = 14,
186 		.rfkill_pin = 48,
187 		.rfkill_cfg = 0,
188 		.rfkill_on_level = 1,
189 		.single_pdev_only = true,
190 		.rxdma1_enable = false,
191 		.num_rxmda_per_pdev = 2,
192 		.rx_mac_buf_ring = true,
193 		.vdev_start_delay = true,
194 		.htt_peer_map_v2 = false,
195 
196 		.spectral = {
197 			.fft_sz = 0,
198 			.fft_pad_sz = 0,
199 			.summary_pad_sz = 0,
200 			.fft_hdr_len = 0,
201 			.max_fft_bins = 0,
202 		},
203 
204 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
205 					BIT(NL80211_IFTYPE_AP),
206 		.supports_monitor = false,
207 		.full_monitor_mode = false,
208 		.supports_shadow_regs = true,
209 		.idle_ps = true,
210 		.supports_sta_ps = true,
211 		.cold_boot_calib = false,
212 		.fw_mem_mode = 0,
213 		.num_vdevs = 16 + 1,
214 		.num_peers = 512,
215 		.supports_suspend = true,
216 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
217 		.supports_regdb = true,
218 		.fix_l1ss = true,
219 		.credit_flow = true,
220 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
221 		.hal_params = &ath11k_hw_hal_params_qca6390,
222 		.supports_dynamic_smps_6ghz = false,
223 		.alloc_cacheable_memory = false,
224 		.wakeup_mhi = true,
225 		.supports_rssi_stats = true,
226 		.fw_wmi_diag_event = true,
227 	},
228 	{
229 		.name = "qcn9074 hw1.0",
230 		.hw_rev = ATH11K_HW_QCN9074_HW10,
231 		.fw = {
232 			.dir = "QCN9074/hw1.0",
233 			.board_size = 256 * 1024,
234 			.cal_offset = 128 * 1024,
235 		},
236 		.max_radios = 1,
237 		.single_pdev_only = false,
238 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074,
239 		.hw_ops = &qcn9074_ops,
240 		.ring_mask = &ath11k_hw_ring_mask_qcn9074,
241 		.internal_sleep_clock = false,
242 		.regs = &qcn9074_regs,
243 		.host_ce_config = ath11k_host_ce_config_qcn9074,
244 		.ce_count = 6,
245 		.target_ce_config = ath11k_target_ce_config_wlan_qcn9074,
246 		.target_ce_count = 9,
247 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
248 		.svc_to_ce_map_len = 18,
249 		.rfkill_pin = 0,
250 		.rfkill_cfg = 0,
251 		.rfkill_on_level = 0,
252 		.rxdma1_enable = true,
253 		.num_rxmda_per_pdev = 1,
254 		.rx_mac_buf_ring = false,
255 		.vdev_start_delay = false,
256 		.htt_peer_map_v2 = true,
257 
258 		.spectral = {
259 			.fft_sz = 2,
260 			.fft_pad_sz = 0,
261 			.summary_pad_sz = 16,
262 			.fft_hdr_len = 24,
263 			.max_fft_bins = 1024,
264 		},
265 
266 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
267 					BIT(NL80211_IFTYPE_AP) |
268 					BIT(NL80211_IFTYPE_MESH_POINT),
269 		.supports_monitor = true,
270 		.full_monitor_mode = true,
271 		.supports_shadow_regs = false,
272 		.idle_ps = false,
273 		.supports_sta_ps = false,
274 		.cold_boot_calib = false,
275 		.fw_mem_mode = 2,
276 		.num_vdevs = 8,
277 		.num_peers = 128,
278 		.supports_suspend = false,
279 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
280 		.supports_regdb = false,
281 		.fix_l1ss = true,
282 		.credit_flow = false,
283 		.max_tx_ring = DP_TCL_NUM_RING_MAX,
284 		.hal_params = &ath11k_hw_hal_params_ipq8074,
285 		.supports_dynamic_smps_6ghz = true,
286 		.alloc_cacheable_memory = true,
287 		.wakeup_mhi = false,
288 		.supports_rssi_stats = false,
289 		.fw_wmi_diag_event = false,
290 	},
291 	{
292 		.name = "wcn6855 hw2.0",
293 		.hw_rev = ATH11K_HW_WCN6855_HW20,
294 		.fw = {
295 			.dir = "WCN6855/hw2.0",
296 			.board_size = 256 * 1024,
297 			.cal_offset = 128 * 1024,
298 		},
299 		.max_radios = 3,
300 		.bdf_addr = 0x4B0C0000,
301 		.hw_ops = &wcn6855_ops,
302 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
303 		.internal_sleep_clock = true,
304 		.regs = &wcn6855_regs,
305 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
306 		.host_ce_config = ath11k_host_ce_config_qca6390,
307 		.ce_count = 9,
308 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
309 		.target_ce_count = 9,
310 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
311 		.svc_to_ce_map_len = 14,
312 		.rfkill_pin = 0,
313 		.rfkill_cfg = 0,
314 		.rfkill_on_level = 0,
315 		.single_pdev_only = true,
316 		.rxdma1_enable = false,
317 		.num_rxmda_per_pdev = 2,
318 		.rx_mac_buf_ring = true,
319 		.vdev_start_delay = true,
320 		.htt_peer_map_v2 = false,
321 
322 		.spectral = {
323 			.fft_sz = 0,
324 			.fft_pad_sz = 0,
325 			.summary_pad_sz = 0,
326 			.fft_hdr_len = 0,
327 			.max_fft_bins = 0,
328 		},
329 
330 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
331 					BIT(NL80211_IFTYPE_AP),
332 		.supports_monitor = false,
333 		.full_monitor_mode = false,
334 		.supports_shadow_regs = true,
335 		.idle_ps = true,
336 		.supports_sta_ps = true,
337 		.cold_boot_calib = false,
338 		.fw_mem_mode = 0,
339 		.num_vdevs = 16 + 1,
340 		.num_peers = 512,
341 		.supports_suspend = true,
342 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
343 		.supports_regdb = true,
344 		.fix_l1ss = false,
345 		.credit_flow = true,
346 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
347 		.hal_params = &ath11k_hw_hal_params_qca6390,
348 		.supports_dynamic_smps_6ghz = false,
349 		.alloc_cacheable_memory = false,
350 		.wakeup_mhi = true,
351 		.supports_rssi_stats = true,
352 		.fw_wmi_diag_event = true,
353 	},
354 	{
355 		.name = "wcn6855 hw2.1",
356 		.hw_rev = ATH11K_HW_WCN6855_HW21,
357 		.fw = {
358 			.dir = "WCN6855/hw2.1",
359 			.board_size = 256 * 1024,
360 			.cal_offset = 128 * 1024,
361 		},
362 		.max_radios = 3,
363 		.bdf_addr = 0x4B0C0000,
364 		.hw_ops = &wcn6855_ops,
365 		.ring_mask = &ath11k_hw_ring_mask_qca6390,
366 		.internal_sleep_clock = true,
367 		.regs = &wcn6855_regs,
368 		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
369 		.host_ce_config = ath11k_host_ce_config_qca6390,
370 		.ce_count = 9,
371 		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
372 		.target_ce_count = 9,
373 		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
374 		.svc_to_ce_map_len = 14,
375 		.rfkill_pin = 0,
376 		.rfkill_cfg = 0,
377 		.rfkill_on_level = 0,
378 		.single_pdev_only = true,
379 		.rxdma1_enable = false,
380 		.num_rxmda_per_pdev = 2,
381 		.rx_mac_buf_ring = true,
382 		.vdev_start_delay = true,
383 		.htt_peer_map_v2 = false,
384 
385 		.spectral = {
386 			.fft_sz = 0,
387 			.fft_pad_sz = 0,
388 			.summary_pad_sz = 0,
389 			.fft_hdr_len = 0,
390 			.max_fft_bins = 0,
391 		},
392 
393 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
394 					BIT(NL80211_IFTYPE_AP),
395 		.supports_monitor = false,
396 		.supports_shadow_regs = true,
397 		.idle_ps = true,
398 		.supports_sta_ps = true,
399 		.cold_boot_calib = false,
400 		.fw_mem_mode = 0,
401 		.num_vdevs = 16 + 1,
402 		.num_peers = 512,
403 		.supports_suspend = true,
404 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
405 		.supports_regdb = true,
406 		.fix_l1ss = false,
407 		.credit_flow = true,
408 		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
409 		.hal_params = &ath11k_hw_hal_params_qca6390,
410 		.supports_dynamic_smps_6ghz = false,
411 		.alloc_cacheable_memory = false,
412 		.wakeup_mhi = true,
413 		.supports_rssi_stats = true,
414 		.fw_wmi_diag_event = true,
415 	},
416 };
417 
418 int ath11k_core_suspend(struct ath11k_base *ab)
419 {
420 	int ret;
421 
422 	if (!ab->hw_params.supports_suspend)
423 		return -EOPNOTSUPP;
424 
425 	/* TODO: there can frames in queues so for now add delay as a hack.
426 	 * Need to implement to handle and remove this delay.
427 	 */
428 	msleep(500);
429 
430 	ret = ath11k_dp_rx_pktlog_stop(ab, true);
431 	if (ret) {
432 		ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
433 			    ret);
434 		return ret;
435 	}
436 
437 	ret = ath11k_wow_enable(ab);
438 	if (ret) {
439 		ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);
440 		return ret;
441 	}
442 
443 	ret = ath11k_dp_rx_pktlog_stop(ab, false);
444 	if (ret) {
445 		ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
446 			    ret);
447 		return ret;
448 	}
449 
450 	ath11k_ce_stop_shadow_timers(ab);
451 	ath11k_dp_stop_shadow_timers(ab);
452 
453 	ath11k_hif_irq_disable(ab);
454 	ath11k_hif_ce_irq_disable(ab);
455 
456 	ret = ath11k_hif_suspend(ab);
457 	if (ret) {
458 		ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
459 		return ret;
460 	}
461 
462 	return 0;
463 }
464 EXPORT_SYMBOL(ath11k_core_suspend);
465 
466 int ath11k_core_resume(struct ath11k_base *ab)
467 {
468 	int ret;
469 
470 	if (!ab->hw_params.supports_suspend)
471 		return -EOPNOTSUPP;
472 
473 	ret = ath11k_hif_resume(ab);
474 	if (ret) {
475 		ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
476 		return ret;
477 	}
478 
479 	ath11k_hif_ce_irq_enable(ab);
480 	ath11k_hif_irq_enable(ab);
481 
482 	ret = ath11k_dp_rx_pktlog_start(ab);
483 	if (ret) {
484 		ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
485 			    ret);
486 		return ret;
487 	}
488 
489 	ret = ath11k_wow_wakeup(ab);
490 	if (ret) {
491 		ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);
492 		return ret;
493 	}
494 
495 	return 0;
496 }
497 EXPORT_SYMBOL(ath11k_core_resume);
498 
499 int ath11k_core_check_dt(struct ath11k_base *ab)
500 {
501 	size_t max_len = sizeof(ab->qmi.target.bdf_ext);
502 	const char *variant = NULL;
503 	struct device_node *node;
504 
505 	node = ab->dev->of_node;
506 	if (!node)
507 		return -ENOENT;
508 
509 	of_property_read_string(node, "qcom,ath11k-calibration-variant",
510 				&variant);
511 	if (!variant)
512 		return -ENODATA;
513 
514 	if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0)
515 		ath11k_dbg(ab, ATH11K_DBG_BOOT,
516 			   "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
517 			    variant);
518 
519 	return 0;
520 }
521 
522 static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
523 					 size_t name_len)
524 {
525 	/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
526 	char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
527 
528 	if (ab->qmi.target.bdf_ext[0] != '\0')
529 		scnprintf(variant, sizeof(variant), ",variant=%s",
530 			  ab->qmi.target.bdf_ext);
531 
532 	switch (ab->id.bdf_search) {
533 	case ATH11K_BDF_SEARCH_BUS_AND_BOARD:
534 		scnprintf(name, name_len,
535 			  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
536 			  ath11k_bus_str(ab->hif.bus),
537 			  ab->id.vendor, ab->id.device,
538 			  ab->id.subsystem_vendor,
539 			  ab->id.subsystem_device,
540 			  ab->qmi.target.chip_id,
541 			  ab->qmi.target.board_id,
542 			  variant);
543 		break;
544 	default:
545 		scnprintf(name, name_len,
546 			  "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
547 			  ath11k_bus_str(ab->hif.bus),
548 			  ab->qmi.target.chip_id,
549 			  ab->qmi.target.board_id, variant);
550 		break;
551 	}
552 
553 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
554 
555 	return 0;
556 }
557 
558 const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
559 						    const char *file)
560 {
561 	const struct firmware *fw;
562 	char path[100];
563 	int ret;
564 
565 	if (file == NULL)
566 		return ERR_PTR(-ENOENT);
567 
568 	ath11k_core_create_firmware_path(ab, file, path, sizeof(path));
569 
570 	ret = firmware_request_nowarn(&fw, path, ab->dev);
571 	if (ret)
572 		return ERR_PTR(ret);
573 
574 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n",
575 		   path, fw->size);
576 
577 	return fw;
578 }
579 
580 void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
581 {
582 	if (!IS_ERR(bd->fw))
583 		release_firmware(bd->fw);
584 
585 	memset(bd, 0, sizeof(*bd));
586 }
587 
588 static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
589 					 struct ath11k_board_data *bd,
590 					 const void *buf, size_t buf_len,
591 					 const char *boardname,
592 					 int bd_ie_type)
593 {
594 	const struct ath11k_fw_ie *hdr;
595 	bool name_match_found;
596 	int ret, board_ie_id;
597 	size_t board_ie_len;
598 	const void *board_ie_data;
599 
600 	name_match_found = false;
601 
602 	/* go through ATH11K_BD_IE_BOARD_ elements */
603 	while (buf_len > sizeof(struct ath11k_fw_ie)) {
604 		hdr = buf;
605 		board_ie_id = le32_to_cpu(hdr->id);
606 		board_ie_len = le32_to_cpu(hdr->len);
607 		board_ie_data = hdr->data;
608 
609 		buf_len -= sizeof(*hdr);
610 		buf += sizeof(*hdr);
611 
612 		if (buf_len < ALIGN(board_ie_len, 4)) {
613 			ath11k_err(ab, "invalid ATH11K_BD_IE_BOARD length: %zu < %zu\n",
614 				   buf_len, ALIGN(board_ie_len, 4));
615 			ret = -EINVAL;
616 			goto out;
617 		}
618 
619 		switch (board_ie_id) {
620 		case ATH11K_BD_IE_BOARD_NAME:
621 			ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "",
622 					board_ie_data, board_ie_len);
623 
624 			if (board_ie_len != strlen(boardname))
625 				break;
626 
627 			ret = memcmp(board_ie_data, boardname, strlen(boardname));
628 			if (ret)
629 				break;
630 
631 			name_match_found = true;
632 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
633 				   "boot found match for name '%s'",
634 				   boardname);
635 			break;
636 		case ATH11K_BD_IE_BOARD_DATA:
637 			if (!name_match_found)
638 				/* no match found */
639 				break;
640 
641 			ath11k_dbg(ab, ATH11K_DBG_BOOT,
642 				   "boot found board data for '%s'", boardname);
643 
644 			bd->data = board_ie_data;
645 			bd->len = board_ie_len;
646 
647 			ret = 0;
648 			goto out;
649 		default:
650 			ath11k_warn(ab, "unknown ATH11K_BD_IE_BOARD found: %d\n",
651 				    board_ie_id);
652 			break;
653 		}
654 
655 		/* jump over the padding */
656 		board_ie_len = ALIGN(board_ie_len, 4);
657 
658 		buf_len -= board_ie_len;
659 		buf += board_ie_len;
660 	}
661 
662 	/* no match found */
663 	ret = -ENOENT;
664 
665 out:
666 	return ret;
667 }
668 
669 static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
670 					      struct ath11k_board_data *bd,
671 					      const char *boardname)
672 {
673 	size_t len, magic_len;
674 	const u8 *data;
675 	char *filename, filepath[100];
676 	size_t ie_len;
677 	struct ath11k_fw_ie *hdr;
678 	int ret, ie_id;
679 
680 	filename = ATH11K_BOARD_API2_FILE;
681 
682 	if (!bd->fw)
683 		bd->fw = ath11k_core_firmware_request(ab, filename);
684 
685 	if (IS_ERR(bd->fw))
686 		return PTR_ERR(bd->fw);
687 
688 	data = bd->fw->data;
689 	len = bd->fw->size;
690 
691 	ath11k_core_create_firmware_path(ab, filename,
692 					 filepath, sizeof(filepath));
693 
694 	/* magic has extra null byte padded */
695 	magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
696 	if (len < magic_len) {
697 		ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
698 			   filepath, len);
699 		ret = -EINVAL;
700 		goto err;
701 	}
702 
703 	if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) {
704 		ath11k_err(ab, "found invalid board magic\n");
705 		ret = -EINVAL;
706 		goto err;
707 	}
708 
709 	/* magic is padded to 4 bytes */
710 	magic_len = ALIGN(magic_len, 4);
711 	if (len < magic_len) {
712 		ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
713 			   filepath, len);
714 		ret = -EINVAL;
715 		goto err;
716 	}
717 
718 	data += magic_len;
719 	len -= magic_len;
720 
721 	while (len > sizeof(struct ath11k_fw_ie)) {
722 		hdr = (struct ath11k_fw_ie *)data;
723 		ie_id = le32_to_cpu(hdr->id);
724 		ie_len = le32_to_cpu(hdr->len);
725 
726 		len -= sizeof(*hdr);
727 		data = hdr->data;
728 
729 		if (len < ALIGN(ie_len, 4)) {
730 			ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
731 				   ie_id, ie_len, len);
732 			ret = -EINVAL;
733 			goto err;
734 		}
735 
736 		switch (ie_id) {
737 		case ATH11K_BD_IE_BOARD:
738 			ret = ath11k_core_parse_bd_ie_board(ab, bd, data,
739 							    ie_len,
740 							    boardname,
741 							    ATH11K_BD_IE_BOARD);
742 			if (ret == -ENOENT)
743 				/* no match found, continue */
744 				break;
745 			else if (ret)
746 				/* there was an error, bail out */
747 				goto err;
748 			/* either found or error, so stop searching */
749 			goto out;
750 		}
751 
752 		/* jump over the padding */
753 		ie_len = ALIGN(ie_len, 4);
754 
755 		len -= ie_len;
756 		data += ie_len;
757 	}
758 
759 out:
760 	if (!bd->data || !bd->len) {
761 		ath11k_err(ab,
762 			   "failed to fetch board data for %s from %s\n",
763 			   boardname, filepath);
764 		ret = -ENODATA;
765 		goto err;
766 	}
767 
768 	return 0;
769 
770 err:
771 	ath11k_core_free_bdf(ab, bd);
772 	return ret;
773 }
774 
775 int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
776 				       struct ath11k_board_data *bd,
777 				       const char *name)
778 {
779 	bd->fw = ath11k_core_firmware_request(ab, name);
780 
781 	if (IS_ERR(bd->fw))
782 		return PTR_ERR(bd->fw);
783 
784 	bd->data = bd->fw->data;
785 	bd->len = bd->fw->size;
786 
787 	return 0;
788 }
789 
790 #define BOARD_NAME_SIZE 200
791 int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
792 {
793 	char boardname[BOARD_NAME_SIZE];
794 	int ret;
795 
796 	ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
797 	if (ret) {
798 		ath11k_err(ab, "failed to create board name: %d", ret);
799 		return ret;
800 	}
801 
802 	ab->bd_api = 2;
803 	ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname);
804 	if (!ret)
805 		goto success;
806 
807 	ab->bd_api = 1;
808 	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);
809 	if (ret) {
810 		ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
811 			   ab->hw_params.fw.dir);
812 		return ret;
813 	}
814 
815 success:
816 	ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
817 	return 0;
818 }
819 
820 int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
821 {
822 	int ret;
823 
824 	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
825 	if (ret)
826 		ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
827 			   ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir);
828 
829 	return ret;
830 }
831 
832 static void ath11k_core_stop(struct ath11k_base *ab)
833 {
834 	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
835 		ath11k_qmi_firmware_stop(ab);
836 
837 	ath11k_hif_stop(ab);
838 	ath11k_wmi_detach(ab);
839 	ath11k_dp_pdev_reo_cleanup(ab);
840 
841 	/* De-Init of components as needed */
842 }
843 
844 static int ath11k_core_soc_create(struct ath11k_base *ab)
845 {
846 	int ret;
847 
848 	ret = ath11k_qmi_init_service(ab);
849 	if (ret) {
850 		ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
851 		return ret;
852 	}
853 
854 	ret = ath11k_debugfs_soc_create(ab);
855 	if (ret) {
856 		ath11k_err(ab, "failed to create ath11k debugfs\n");
857 		goto err_qmi_deinit;
858 	}
859 
860 	ret = ath11k_hif_power_up(ab);
861 	if (ret) {
862 		ath11k_err(ab, "failed to power up :%d\n", ret);
863 		goto err_debugfs_reg;
864 	}
865 
866 	return 0;
867 
868 err_debugfs_reg:
869 	ath11k_debugfs_soc_destroy(ab);
870 err_qmi_deinit:
871 	ath11k_qmi_deinit_service(ab);
872 	return ret;
873 }
874 
875 static void ath11k_core_soc_destroy(struct ath11k_base *ab)
876 {
877 	ath11k_debugfs_soc_destroy(ab);
878 	ath11k_dp_free(ab);
879 	ath11k_reg_free(ab);
880 	ath11k_qmi_deinit_service(ab);
881 }
882 
883 static int ath11k_core_pdev_create(struct ath11k_base *ab)
884 {
885 	int ret;
886 
887 	ret = ath11k_debugfs_pdev_create(ab);
888 	if (ret) {
889 		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
890 		return ret;
891 	}
892 
893 	ret = ath11k_mac_register(ab);
894 	if (ret) {
895 		ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
896 		goto err_pdev_debug;
897 	}
898 
899 	ret = ath11k_dp_pdev_alloc(ab);
900 	if (ret) {
901 		ath11k_err(ab, "failed to attach DP pdev: %d\n", ret);
902 		goto err_mac_unregister;
903 	}
904 
905 	ret = ath11k_thermal_register(ab);
906 	if (ret) {
907 		ath11k_err(ab, "could not register thermal device: %d\n",
908 			   ret);
909 		goto err_dp_pdev_free;
910 	}
911 
912 	ret = ath11k_spectral_init(ab);
913 	if (ret) {
914 		ath11k_err(ab, "failed to init spectral %d\n", ret);
915 		goto err_thermal_unregister;
916 	}
917 
918 	return 0;
919 
920 err_thermal_unregister:
921 	ath11k_thermal_unregister(ab);
922 err_dp_pdev_free:
923 	ath11k_dp_pdev_free(ab);
924 err_mac_unregister:
925 	ath11k_mac_unregister(ab);
926 err_pdev_debug:
927 	ath11k_debugfs_pdev_destroy(ab);
928 
929 	return ret;
930 }
931 
932 static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
933 {
934 	ath11k_spectral_deinit(ab);
935 	ath11k_thermal_unregister(ab);
936 	ath11k_mac_unregister(ab);
937 	ath11k_hif_irq_disable(ab);
938 	ath11k_dp_pdev_free(ab);
939 	ath11k_debugfs_pdev_destroy(ab);
940 }
941 
942 static int ath11k_core_start(struct ath11k_base *ab,
943 			     enum ath11k_firmware_mode mode)
944 {
945 	int ret;
946 
947 	ret = ath11k_qmi_firmware_start(ab, mode);
948 	if (ret) {
949 		ath11k_err(ab, "failed to attach wmi: %d\n", ret);
950 		return ret;
951 	}
952 
953 	ret = ath11k_wmi_attach(ab);
954 	if (ret) {
955 		ath11k_err(ab, "failed to attach wmi: %d\n", ret);
956 		goto err_firmware_stop;
957 	}
958 
959 	ret = ath11k_htc_init(ab);
960 	if (ret) {
961 		ath11k_err(ab, "failed to init htc: %d\n", ret);
962 		goto err_wmi_detach;
963 	}
964 
965 	ret = ath11k_hif_start(ab);
966 	if (ret) {
967 		ath11k_err(ab, "failed to start HIF: %d\n", ret);
968 		goto err_wmi_detach;
969 	}
970 
971 	ret = ath11k_htc_wait_target(&ab->htc);
972 	if (ret) {
973 		ath11k_err(ab, "failed to connect to HTC: %d\n", ret);
974 		goto err_hif_stop;
975 	}
976 
977 	ret = ath11k_dp_htt_connect(&ab->dp);
978 	if (ret) {
979 		ath11k_err(ab, "failed to connect to HTT: %d\n", ret);
980 		goto err_hif_stop;
981 	}
982 
983 	ret = ath11k_wmi_connect(ab);
984 	if (ret) {
985 		ath11k_err(ab, "failed to connect wmi: %d\n", ret);
986 		goto err_hif_stop;
987 	}
988 
989 	ret = ath11k_htc_start(&ab->htc);
990 	if (ret) {
991 		ath11k_err(ab, "failed to start HTC: %d\n", ret);
992 		goto err_hif_stop;
993 	}
994 
995 	ret = ath11k_wmi_wait_for_service_ready(ab);
996 	if (ret) {
997 		ath11k_err(ab, "failed to receive wmi service ready event: %d\n",
998 			   ret);
999 		goto err_hif_stop;
1000 	}
1001 
1002 	ret = ath11k_mac_allocate(ab);
1003 	if (ret) {
1004 		ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n",
1005 			   ret);
1006 		goto err_hif_stop;
1007 	}
1008 
1009 	ath11k_dp_pdev_pre_alloc(ab);
1010 
1011 	ret = ath11k_dp_pdev_reo_setup(ab);
1012 	if (ret) {
1013 		ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
1014 		goto err_mac_destroy;
1015 	}
1016 
1017 	ret = ath11k_wmi_cmd_init(ab);
1018 	if (ret) {
1019 		ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret);
1020 		goto err_reo_cleanup;
1021 	}
1022 
1023 	ret = ath11k_wmi_wait_for_unified_ready(ab);
1024 	if (ret) {
1025 		ath11k_err(ab, "failed to receive wmi unified ready event: %d\n",
1026 			   ret);
1027 		goto err_reo_cleanup;
1028 	}
1029 
1030 	/* put hardware to DBS mode */
1031 	if (ab->hw_params.single_pdev_only) {
1032 		ret = ath11k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
1033 		if (ret) {
1034 			ath11k_err(ab, "failed to send dbs mode: %d\n", ret);
1035 			goto err_hif_stop;
1036 		}
1037 	}
1038 
1039 	ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);
1040 	if (ret) {
1041 		ath11k_err(ab, "failed to send htt version request message: %d\n",
1042 			   ret);
1043 		goto err_reo_cleanup;
1044 	}
1045 
1046 	return 0;
1047 
1048 err_reo_cleanup:
1049 	ath11k_dp_pdev_reo_cleanup(ab);
1050 err_mac_destroy:
1051 	ath11k_mac_destroy(ab);
1052 err_hif_stop:
1053 	ath11k_hif_stop(ab);
1054 err_wmi_detach:
1055 	ath11k_wmi_detach(ab);
1056 err_firmware_stop:
1057 	ath11k_qmi_firmware_stop(ab);
1058 
1059 	return ret;
1060 }
1061 
1062 static int ath11k_core_rfkill_config(struct ath11k_base *ab)
1063 {
1064 	struct ath11k *ar;
1065 	int ret = 0, i;
1066 
1067 	if (!(ab->target_caps.sys_cap_info & WMI_SYS_CAP_INFO_RFKILL))
1068 		return 0;
1069 
1070 	for (i = 0; i < ab->num_radios; i++) {
1071 		ar = ab->pdevs[i].ar;
1072 
1073 		ret = ath11k_mac_rfkill_config(ar);
1074 		if (ret && ret != -EOPNOTSUPP) {
1075 			ath11k_warn(ab, "failed to configure rfkill: %d", ret);
1076 			return ret;
1077 		}
1078 	}
1079 
1080 	return ret;
1081 }
1082 
1083 int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
1084 {
1085 	int ret;
1086 
1087 	ret = ath11k_ce_init_pipes(ab);
1088 	if (ret) {
1089 		ath11k_err(ab, "failed to initialize CE: %d\n", ret);
1090 		return ret;
1091 	}
1092 
1093 	ret = ath11k_dp_alloc(ab);
1094 	if (ret) {
1095 		ath11k_err(ab, "failed to init DP: %d\n", ret);
1096 		return ret;
1097 	}
1098 
1099 	switch (ath11k_crypto_mode) {
1100 	case ATH11K_CRYPT_MODE_SW:
1101 		set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1102 		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1103 		break;
1104 	case ATH11K_CRYPT_MODE_HW:
1105 		clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1106 		clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1107 		break;
1108 	default:
1109 		ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
1110 		return -EINVAL;
1111 	}
1112 
1113 	if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
1114 		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1115 
1116 	mutex_lock(&ab->core_lock);
1117 	ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL);
1118 	if (ret) {
1119 		ath11k_err(ab, "failed to start core: %d\n", ret);
1120 		goto err_dp_free;
1121 	}
1122 
1123 	ret = ath11k_core_pdev_create(ab);
1124 	if (ret) {
1125 		ath11k_err(ab, "failed to create pdev core: %d\n", ret);
1126 		goto err_core_stop;
1127 	}
1128 	ath11k_hif_irq_enable(ab);
1129 
1130 	ret = ath11k_core_rfkill_config(ab);
1131 	if (ret && ret != -EOPNOTSUPP) {
1132 		ath11k_err(ab, "failed to config rfkill: %d\n", ret);
1133 		goto err_core_stop;
1134 	}
1135 
1136 	mutex_unlock(&ab->core_lock);
1137 
1138 	return 0;
1139 
1140 err_core_stop:
1141 	ath11k_core_stop(ab);
1142 	ath11k_mac_destroy(ab);
1143 err_dp_free:
1144 	ath11k_dp_free(ab);
1145 	mutex_unlock(&ab->core_lock);
1146 	return ret;
1147 }
1148 
1149 static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
1150 {
1151 	int ret;
1152 
1153 	mutex_lock(&ab->core_lock);
1154 	ath11k_thermal_unregister(ab);
1155 	ath11k_hif_irq_disable(ab);
1156 	ath11k_dp_pdev_free(ab);
1157 	ath11k_spectral_deinit(ab);
1158 	ath11k_hif_stop(ab);
1159 	ath11k_wmi_detach(ab);
1160 	ath11k_dp_pdev_reo_cleanup(ab);
1161 	mutex_unlock(&ab->core_lock);
1162 
1163 	ath11k_dp_free(ab);
1164 	ath11k_hal_srng_deinit(ab);
1165 
1166 	ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
1167 
1168 	ret = ath11k_hal_srng_init(ab);
1169 	if (ret)
1170 		return ret;
1171 
1172 	clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
1173 
1174 	ret = ath11k_core_qmi_firmware_ready(ab);
1175 	if (ret)
1176 		goto err_hal_srng_deinit;
1177 
1178 	clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
1179 
1180 	return 0;
1181 
1182 err_hal_srng_deinit:
1183 	ath11k_hal_srng_deinit(ab);
1184 	return ret;
1185 }
1186 
1187 void ath11k_core_halt(struct ath11k *ar)
1188 {
1189 	struct ath11k_base *ab = ar->ab;
1190 
1191 	lockdep_assert_held(&ar->conf_mutex);
1192 
1193 	ar->num_created_vdevs = 0;
1194 	ar->allocated_vdev_map = 0;
1195 
1196 	ath11k_mac_scan_finish(ar);
1197 	ath11k_mac_peer_cleanup_all(ar);
1198 	cancel_delayed_work_sync(&ar->scan.timeout);
1199 	cancel_work_sync(&ar->regd_update_work);
1200 	cancel_work_sync(&ab->update_11d_work);
1201 	cancel_work_sync(&ab->rfkill_work);
1202 
1203 	rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
1204 	synchronize_rcu();
1205 	INIT_LIST_HEAD(&ar->arvifs);
1206 	idr_init(&ar->txmgmt_idr);
1207 }
1208 
1209 static void ath11k_rfkill_work(struct work_struct *work)
1210 {
1211 	struct ath11k_base *ab = container_of(work, struct ath11k_base, rfkill_work);
1212 	struct ath11k *ar;
1213 	bool rfkill_radio_on;
1214 	int i;
1215 
1216 	spin_lock_bh(&ab->base_lock);
1217 	rfkill_radio_on = ab->rfkill_radio_on;
1218 	spin_unlock_bh(&ab->base_lock);
1219 
1220 	for (i = 0; i < ab->num_radios; i++) {
1221 		ar = ab->pdevs[i].ar;
1222 		if (!ar)
1223 			continue;
1224 
1225 		/* notify cfg80211 radio state change */
1226 		ath11k_mac_rfkill_enable_radio(ar, rfkill_radio_on);
1227 		wiphy_rfkill_set_hw_state(ar->hw->wiphy, !rfkill_radio_on);
1228 	}
1229 }
1230 
1231 static void ath11k_update_11d(struct work_struct *work)
1232 {
1233 	struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
1234 	struct ath11k *ar;
1235 	struct ath11k_pdev *pdev;
1236 	struct wmi_set_current_country_params set_current_param = {};
1237 	int ret, i;
1238 
1239 	spin_lock_bh(&ab->base_lock);
1240 	memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);
1241 	spin_unlock_bh(&ab->base_lock);
1242 
1243 	ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",
1244 		   set_current_param.alpha2[0],
1245 		   set_current_param.alpha2[1]);
1246 
1247 	for (i = 0; i < ab->num_radios; i++) {
1248 		pdev = &ab->pdevs[i];
1249 		ar = pdev->ar;
1250 
1251 		ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
1252 		if (ret)
1253 			ath11k_warn(ar->ab,
1254 				    "pdev id %d failed set current country code: %d\n",
1255 				    i, ret);
1256 	}
1257 }
1258 
1259 static void ath11k_core_restart(struct work_struct *work)
1260 {
1261 	struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
1262 	struct ath11k *ar;
1263 	struct ath11k_pdev *pdev;
1264 	int i, ret = 0;
1265 
1266 	spin_lock_bh(&ab->base_lock);
1267 	ab->stats.fw_crash_counter++;
1268 	spin_unlock_bh(&ab->base_lock);
1269 
1270 	for (i = 0; i < ab->num_radios; i++) {
1271 		pdev = &ab->pdevs[i];
1272 		ar = pdev->ar;
1273 		if (!ar || ar->state == ATH11K_STATE_OFF)
1274 			continue;
1275 
1276 		ieee80211_stop_queues(ar->hw);
1277 		ath11k_mac_drain_tx(ar);
1278 		complete(&ar->scan.started);
1279 		complete(&ar->scan.completed);
1280 		complete(&ar->peer_assoc_done);
1281 		complete(&ar->peer_delete_done);
1282 		complete(&ar->install_key_done);
1283 		complete(&ar->vdev_setup_done);
1284 		complete(&ar->vdev_delete_done);
1285 		complete(&ar->bss_survey_done);
1286 		complete(&ar->thermal.wmi_sync);
1287 
1288 		wake_up(&ar->dp.tx_empty_waitq);
1289 		idr_for_each(&ar->txmgmt_idr,
1290 			     ath11k_mac_tx_mgmt_pending_free, ar);
1291 		idr_destroy(&ar->txmgmt_idr);
1292 		wake_up(&ar->txmgmt_empty_waitq);
1293 	}
1294 
1295 	wake_up(&ab->wmi_ab.tx_credits_wq);
1296 	wake_up(&ab->peer_mapping_wq);
1297 
1298 	ret = ath11k_core_reconfigure_on_crash(ab);
1299 	if (ret) {
1300 		ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
1301 		return;
1302 	}
1303 
1304 	for (i = 0; i < ab->num_radios; i++) {
1305 		pdev = &ab->pdevs[i];
1306 		ar = pdev->ar;
1307 		if (!ar || ar->state == ATH11K_STATE_OFF)
1308 			continue;
1309 
1310 		mutex_lock(&ar->conf_mutex);
1311 
1312 		switch (ar->state) {
1313 		case ATH11K_STATE_ON:
1314 			ar->state = ATH11K_STATE_RESTARTING;
1315 			ath11k_core_halt(ar);
1316 			ieee80211_restart_hw(ar->hw);
1317 			break;
1318 		case ATH11K_STATE_OFF:
1319 			ath11k_warn(ab,
1320 				    "cannot restart radio %d that hasn't been started\n",
1321 				    i);
1322 			break;
1323 		case ATH11K_STATE_RESTARTING:
1324 			break;
1325 		case ATH11K_STATE_RESTARTED:
1326 			ar->state = ATH11K_STATE_WEDGED;
1327 			fallthrough;
1328 		case ATH11K_STATE_WEDGED:
1329 			ath11k_warn(ab,
1330 				    "device is wedged, will not restart radio %d\n", i);
1331 			break;
1332 		}
1333 		mutex_unlock(&ar->conf_mutex);
1334 	}
1335 	complete(&ab->driver_recovery);
1336 }
1337 
1338 static int ath11k_init_hw_params(struct ath11k_base *ab)
1339 {
1340 	const struct ath11k_hw_params *hw_params = NULL;
1341 	int i;
1342 
1343 	for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
1344 		hw_params = &ath11k_hw_params[i];
1345 
1346 		if (hw_params->hw_rev == ab->hw_rev)
1347 			break;
1348 	}
1349 
1350 	if (i == ARRAY_SIZE(ath11k_hw_params)) {
1351 		ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);
1352 		return -EINVAL;
1353 	}
1354 
1355 	ab->hw_params = *hw_params;
1356 
1357 	ath11k_info(ab, "%s\n", ab->hw_params.name);
1358 
1359 	return 0;
1360 }
1361 
1362 int ath11k_core_pre_init(struct ath11k_base *ab)
1363 {
1364 	int ret;
1365 
1366 	ret = ath11k_init_hw_params(ab);
1367 	if (ret) {
1368 		ath11k_err(ab, "failed to get hw params: %d\n", ret);
1369 		return ret;
1370 	}
1371 
1372 	return 0;
1373 }
1374 EXPORT_SYMBOL(ath11k_core_pre_init);
1375 
1376 int ath11k_core_init(struct ath11k_base *ab)
1377 {
1378 	int ret;
1379 
1380 	ret = ath11k_core_soc_create(ab);
1381 	if (ret) {
1382 		ath11k_err(ab, "failed to create soc core: %d\n", ret);
1383 		return ret;
1384 	}
1385 
1386 	return 0;
1387 }
1388 EXPORT_SYMBOL(ath11k_core_init);
1389 
1390 void ath11k_core_deinit(struct ath11k_base *ab)
1391 {
1392 	mutex_lock(&ab->core_lock);
1393 
1394 	ath11k_core_pdev_destroy(ab);
1395 	ath11k_core_stop(ab);
1396 
1397 	mutex_unlock(&ab->core_lock);
1398 
1399 	ath11k_hif_power_down(ab);
1400 	ath11k_mac_destroy(ab);
1401 	ath11k_core_soc_destroy(ab);
1402 }
1403 EXPORT_SYMBOL(ath11k_core_deinit);
1404 
1405 void ath11k_core_free(struct ath11k_base *ab)
1406 {
1407 	kfree(ab);
1408 }
1409 EXPORT_SYMBOL(ath11k_core_free);
1410 
1411 struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
1412 				      enum ath11k_bus bus,
1413 				      const struct ath11k_bus_params *bus_params)
1414 {
1415 	struct ath11k_base *ab;
1416 
1417 	ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);
1418 	if (!ab)
1419 		return NULL;
1420 
1421 	init_completion(&ab->driver_recovery);
1422 
1423 	ab->workqueue = create_singlethread_workqueue("ath11k_wq");
1424 	if (!ab->workqueue)
1425 		goto err_sc_free;
1426 
1427 	mutex_init(&ab->core_lock);
1428 	spin_lock_init(&ab->base_lock);
1429 	mutex_init(&ab->vdev_id_11d_lock);
1430 
1431 	INIT_LIST_HEAD(&ab->peers);
1432 	init_waitqueue_head(&ab->peer_mapping_wq);
1433 	init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
1434 	init_waitqueue_head(&ab->qmi.cold_boot_waitq);
1435 	INIT_WORK(&ab->restart_work, ath11k_core_restart);
1436 	INIT_WORK(&ab->update_11d_work, ath11k_update_11d);
1437 	INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work);
1438 	timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
1439 	init_completion(&ab->htc_suspend);
1440 	init_completion(&ab->wow.wakeup_completed);
1441 
1442 	ab->dev = dev;
1443 	ab->bus_params = *bus_params;
1444 	ab->hif.bus = bus;
1445 
1446 	return ab;
1447 
1448 err_sc_free:
1449 	kfree(ab);
1450 	return NULL;
1451 }
1452 EXPORT_SYMBOL(ath11k_core_alloc);
1453 
1454 MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
1455 MODULE_LICENSE("Dual BSD/GPL");
1456