Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/*
   3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
   4 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/slab.h>
   9#include <linux/remoteproc.h>
  10#include <linux/firmware.h>
  11#include <linux/of.h>
  12
  13#include "core.h"
  14#include "dp_tx.h"
  15#include "dp_rx.h"
  16#include "debug.h"
  17#include "hif.h"
  18#include "wow.h"
  19
  20unsigned int ath11k_debug_mask;
  21EXPORT_SYMBOL(ath11k_debug_mask);
  22module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
  23MODULE_PARM_DESC(debug_mask, "Debugging mask");
  24
  25static unsigned int ath11k_crypto_mode;
  26module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);
  27MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
  28
  29/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
  30unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
  31module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
  32MODULE_PARM_DESC(frame_mode,
  33		 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
  34
  35static const struct ath11k_hw_params ath11k_hw_params[] = {
  36	{
  37		.hw_rev = ATH11K_HW_IPQ8074,
  38		.name = "ipq8074 hw2.0",
  39		.fw = {
  40			.dir = "IPQ8074/hw2.0",
  41			.board_size = 256 * 1024,
  42			.cal_offset = 128 * 1024,
  43		},
  44		.max_radios = 3,
  45		.bdf_addr = 0x4B0C0000,
  46		.hw_ops = &ipq8074_ops,
  47		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
  48		.internal_sleep_clock = false,
  49		.regs = &ipq8074_regs,
  50		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
  51		.host_ce_config = ath11k_host_ce_config_ipq8074,
  52		.ce_count = 12,
  53		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
  54		.target_ce_count = 11,
  55		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
  56		.svc_to_ce_map_len = 21,
  57		.single_pdev_only = false,
  58		.rxdma1_enable = true,
  59		.num_rxmda_per_pdev = 1,
  60		.rx_mac_buf_ring = false,
  61		.vdev_start_delay = false,
  62		.htt_peer_map_v2 = true,
  63
  64		.spectral = {
  65			.fft_sz = 2,
  66			/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes.
  67			 * so added pad size as 2 bytes to compensate the BIN size
  68			 */
  69			.fft_pad_sz = 2,
  70			.summary_pad_sz = 0,
  71			.fft_hdr_len = 16,
  72			.max_fft_bins = 512,
  73			.fragment_160mhz = true,
  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		.cbcal_restart_fw = true,
  86		.fw_mem_mode = 0,
  87		.num_vdevs = 16 + 1,
  88		.num_peers = 512,
  89		.supports_suspend = false,
  90		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
  91		.supports_regdb = false,
  92		.fix_l1ss = true,
  93		.credit_flow = false,
  94		.max_tx_ring = DP_TCL_NUM_RING_MAX,
  95		.hal_params = &ath11k_hw_hal_params_ipq8074,
  96		.supports_dynamic_smps_6ghz = false,
  97		.alloc_cacheable_memory = true,
  98		.supports_rssi_stats = false,
  99		.fw_wmi_diag_event = false,
 100		.current_cc_support = false,
 101		.dbr_debug_support = true,
 102		.global_reset = false,
 103		.bios_sar_capa = NULL,
 104		.m3_fw_support = false,
 105		.fixed_bdf_addr = true,
 106		.fixed_mem_region = true,
 107		.static_window_map = false,
 108		.hybrid_bus_type = false,
 109		.fixed_fw_mem = false,
 110		.support_off_channel_tx = false,
 111		.supports_multi_bssid = false,
 112
 113		.sram_dump = {},
 114
 115		.tcl_ring_retry = true,
 116		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 117		.smp2p_wow_exit = false,
 118	},
 119	{
 120		.hw_rev = ATH11K_HW_IPQ6018_HW10,
 121		.name = "ipq6018 hw1.0",
 122		.fw = {
 123			.dir = "IPQ6018/hw1.0",
 124			.board_size = 256 * 1024,
 125			.cal_offset = 128 * 1024,
 126		},
 127		.max_radios = 2,
 128		.bdf_addr = 0x4ABC0000,
 129		.hw_ops = &ipq6018_ops,
 130		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
 131		.internal_sleep_clock = false,
 132		.regs = &ipq8074_regs,
 133		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
 134		.host_ce_config = ath11k_host_ce_config_ipq8074,
 135		.ce_count = 12,
 136		.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
 137		.target_ce_count = 11,
 138		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
 139		.svc_to_ce_map_len = 19,
 140		.single_pdev_only = false,
 141		.rxdma1_enable = true,
 142		.num_rxmda_per_pdev = 1,
 143		.rx_mac_buf_ring = false,
 144		.vdev_start_delay = false,
 145		.htt_peer_map_v2 = true,
 146
 147		.spectral = {
 148			.fft_sz = 4,
 149			.fft_pad_sz = 0,
 150			.summary_pad_sz = 0,
 151			.fft_hdr_len = 16,
 152			.max_fft_bins = 512,
 153			.fragment_160mhz = true,
 154		},
 155
 156		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 157					BIT(NL80211_IFTYPE_AP) |
 158					BIT(NL80211_IFTYPE_MESH_POINT),
 159		.supports_monitor = true,
 160		.full_monitor_mode = false,
 161		.supports_shadow_regs = false,
 162		.idle_ps = false,
 163		.supports_sta_ps = false,
 164		.cold_boot_calib = true,
 165		.cbcal_restart_fw = true,
 166		.fw_mem_mode = 0,
 167		.num_vdevs = 16 + 1,
 168		.num_peers = 512,
 169		.supports_suspend = false,
 170		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 171		.supports_regdb = false,
 172		.fix_l1ss = true,
 173		.credit_flow = false,
 174		.max_tx_ring = DP_TCL_NUM_RING_MAX,
 175		.hal_params = &ath11k_hw_hal_params_ipq8074,
 176		.supports_dynamic_smps_6ghz = false,
 177		.alloc_cacheable_memory = true,
 178		.supports_rssi_stats = false,
 179		.fw_wmi_diag_event = false,
 180		.current_cc_support = false,
 181		.dbr_debug_support = true,
 182		.global_reset = false,
 183		.bios_sar_capa = NULL,
 184		.m3_fw_support = false,
 185		.fixed_bdf_addr = true,
 186		.fixed_mem_region = true,
 187		.static_window_map = false,
 188		.hybrid_bus_type = false,
 189		.fixed_fw_mem = false,
 190		.support_off_channel_tx = false,
 191		.supports_multi_bssid = false,
 192
 193		.sram_dump = {},
 194
 195		.tcl_ring_retry = true,
 196		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 197		.smp2p_wow_exit = false,
 198		.support_fw_mac_sequence = false,
 199	},
 200	{
 201		.name = "qca6390 hw2.0",
 202		.hw_rev = ATH11K_HW_QCA6390_HW20,
 203		.fw = {
 204			.dir = "QCA6390/hw2.0",
 205			.board_size = 256 * 1024,
 206			.cal_offset = 128 * 1024,
 207		},
 208		.max_radios = 3,
 209		.bdf_addr = 0x4B0C0000,
 210		.hw_ops = &qca6390_ops,
 211		.ring_mask = &ath11k_hw_ring_mask_qca6390,
 212		.internal_sleep_clock = true,
 213		.regs = &qca6390_regs,
 214		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
 215		.host_ce_config = ath11k_host_ce_config_qca6390,
 216		.ce_count = 9,
 217		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
 218		.target_ce_count = 9,
 219		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
 220		.svc_to_ce_map_len = 14,
 221		.single_pdev_only = true,
 222		.rxdma1_enable = false,
 223		.num_rxmda_per_pdev = 2,
 224		.rx_mac_buf_ring = true,
 225		.vdev_start_delay = true,
 226		.htt_peer_map_v2 = false,
 227
 228		.spectral = {
 229			.fft_sz = 0,
 230			.fft_pad_sz = 0,
 231			.summary_pad_sz = 0,
 232			.fft_hdr_len = 0,
 233			.max_fft_bins = 0,
 234			.fragment_160mhz = false,
 235		},
 236
 237		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 238					BIT(NL80211_IFTYPE_AP),
 239		.supports_monitor = false,
 240		.full_monitor_mode = false,
 241		.supports_shadow_regs = true,
 242		.idle_ps = true,
 243		.supports_sta_ps = true,
 244		.cold_boot_calib = false,
 245		.cbcal_restart_fw = false,
 246		.fw_mem_mode = 0,
 247		.num_vdevs = 16 + 1,
 248		.num_peers = 512,
 249		.supports_suspend = true,
 250		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 251		.supports_regdb = false,
 252		.fix_l1ss = true,
 253		.credit_flow = true,
 254		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
 255		.hal_params = &ath11k_hw_hal_params_qca6390,
 256		.supports_dynamic_smps_6ghz = false,
 257		.alloc_cacheable_memory = false,
 258		.supports_rssi_stats = true,
 259		.fw_wmi_diag_event = true,
 260		.current_cc_support = true,
 261		.dbr_debug_support = false,
 262		.global_reset = true,
 263		.bios_sar_capa = NULL,
 264		.m3_fw_support = true,
 265		.fixed_bdf_addr = false,
 266		.fixed_mem_region = false,
 267		.static_window_map = false,
 268		.hybrid_bus_type = false,
 269		.fixed_fw_mem = false,
 270		.support_off_channel_tx = true,
 271		.supports_multi_bssid = true,
 272
 273		.sram_dump = {
 274			.start = 0x01400000,
 275			.end = 0x0171ffff,
 276		},
 277
 278		.tcl_ring_retry = true,
 279		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 280		.smp2p_wow_exit = false,
 281		.support_fw_mac_sequence = true,
 282	},
 283	{
 284		.name = "qcn9074 hw1.0",
 285		.hw_rev = ATH11K_HW_QCN9074_HW10,
 286		.fw = {
 287			.dir = "QCN9074/hw1.0",
 288			.board_size = 256 * 1024,
 289			.cal_offset = 128 * 1024,
 290		},
 291		.max_radios = 1,
 292		.single_pdev_only = false,
 293		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074,
 294		.hw_ops = &qcn9074_ops,
 295		.ring_mask = &ath11k_hw_ring_mask_qcn9074,
 296		.internal_sleep_clock = false,
 297		.regs = &qcn9074_regs,
 298		.host_ce_config = ath11k_host_ce_config_qcn9074,
 299		.ce_count = 6,
 300		.target_ce_config = ath11k_target_ce_config_wlan_qcn9074,
 301		.target_ce_count = 9,
 302		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
 303		.svc_to_ce_map_len = 18,
 304		.rxdma1_enable = true,
 305		.num_rxmda_per_pdev = 1,
 306		.rx_mac_buf_ring = false,
 307		.vdev_start_delay = false,
 308		.htt_peer_map_v2 = true,
 309
 310		.spectral = {
 311			.fft_sz = 2,
 312			.fft_pad_sz = 0,
 313			.summary_pad_sz = 16,
 314			.fft_hdr_len = 24,
 315			.max_fft_bins = 1024,
 316			.fragment_160mhz = false,
 317		},
 318
 319		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 320					BIT(NL80211_IFTYPE_AP) |
 321					BIT(NL80211_IFTYPE_MESH_POINT),
 322		.supports_monitor = true,
 323		.full_monitor_mode = true,
 324		.supports_shadow_regs = false,
 325		.idle_ps = false,
 326		.supports_sta_ps = false,
 327		.cold_boot_calib = false,
 328		.cbcal_restart_fw = false,
 329		.fw_mem_mode = 2,
 330		.num_vdevs = 8,
 331		.num_peers = 128,
 332		.supports_suspend = false,
 333		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
 334		.supports_regdb = false,
 335		.fix_l1ss = true,
 336		.credit_flow = false,
 337		.max_tx_ring = DP_TCL_NUM_RING_MAX,
 338		.hal_params = &ath11k_hw_hal_params_ipq8074,
 339		.supports_dynamic_smps_6ghz = true,
 340		.alloc_cacheable_memory = true,
 341		.supports_rssi_stats = false,
 342		.fw_wmi_diag_event = false,
 343		.current_cc_support = false,
 344		.dbr_debug_support = true,
 345		.global_reset = false,
 346		.bios_sar_capa = NULL,
 347		.m3_fw_support = true,
 348		.fixed_bdf_addr = false,
 349		.fixed_mem_region = false,
 350		.static_window_map = true,
 351		.hybrid_bus_type = false,
 352		.fixed_fw_mem = false,
 353		.support_off_channel_tx = false,
 354		.supports_multi_bssid = false,
 355
 356		.sram_dump = {},
 357
 358		.tcl_ring_retry = true,
 359		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 360		.smp2p_wow_exit = false,
 361		.support_fw_mac_sequence = false,
 362	},
 363	{
 364		.name = "wcn6855 hw2.0",
 365		.hw_rev = ATH11K_HW_WCN6855_HW20,
 366		.fw = {
 367			.dir = "WCN6855/hw2.0",
 368			.board_size = 256 * 1024,
 369			.cal_offset = 128 * 1024,
 370		},
 371		.max_radios = 3,
 372		.bdf_addr = 0x4B0C0000,
 373		.hw_ops = &wcn6855_ops,
 374		.ring_mask = &ath11k_hw_ring_mask_qca6390,
 375		.internal_sleep_clock = true,
 376		.regs = &wcn6855_regs,
 377		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
 378		.host_ce_config = ath11k_host_ce_config_qca6390,
 379		.ce_count = 9,
 380		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
 381		.target_ce_count = 9,
 382		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
 383		.svc_to_ce_map_len = 14,
 384		.single_pdev_only = true,
 385		.rxdma1_enable = false,
 386		.num_rxmda_per_pdev = 2,
 387		.rx_mac_buf_ring = true,
 388		.vdev_start_delay = true,
 389		.htt_peer_map_v2 = false,
 390
 391		.spectral = {
 392			.fft_sz = 0,
 393			.fft_pad_sz = 0,
 394			.summary_pad_sz = 0,
 395			.fft_hdr_len = 0,
 396			.max_fft_bins = 0,
 397			.fragment_160mhz = false,
 398		},
 399
 400		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 401					BIT(NL80211_IFTYPE_AP),
 402		.supports_monitor = false,
 403		.full_monitor_mode = false,
 404		.supports_shadow_regs = true,
 405		.idle_ps = true,
 406		.supports_sta_ps = true,
 407		.cold_boot_calib = false,
 408		.cbcal_restart_fw = false,
 409		.fw_mem_mode = 0,
 410		.num_vdevs = 16 + 1,
 411		.num_peers = 512,
 412		.supports_suspend = true,
 413		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
 414		.supports_regdb = true,
 415		.fix_l1ss = false,
 416		.credit_flow = true,
 417		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
 418		.hal_params = &ath11k_hw_hal_params_qca6390,
 419		.supports_dynamic_smps_6ghz = false,
 420		.alloc_cacheable_memory = false,
 421		.supports_rssi_stats = true,
 422		.fw_wmi_diag_event = true,
 423		.current_cc_support = true,
 424		.dbr_debug_support = false,
 425		.global_reset = true,
 426		.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
 427		.m3_fw_support = true,
 428		.fixed_bdf_addr = false,
 429		.fixed_mem_region = false,
 430		.static_window_map = false,
 431		.hybrid_bus_type = false,
 432		.fixed_fw_mem = false,
 433		.support_off_channel_tx = true,
 434		.supports_multi_bssid = true,
 435
 436		.sram_dump = {
 437			.start = 0x01400000,
 438			.end = 0x0177ffff,
 439		},
 440
 441		.tcl_ring_retry = true,
 442		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 443		.smp2p_wow_exit = false,
 444		.support_fw_mac_sequence = true,
 445	},
 446	{
 447		.name = "wcn6855 hw2.1",
 448		.hw_rev = ATH11K_HW_WCN6855_HW21,
 449		.fw = {
 450			.dir = "WCN6855/hw2.1",
 451			.board_size = 256 * 1024,
 452			.cal_offset = 128 * 1024,
 453		},
 454		.max_radios = 3,
 455		.bdf_addr = 0x4B0C0000,
 456		.hw_ops = &wcn6855_ops,
 457		.ring_mask = &ath11k_hw_ring_mask_qca6390,
 458		.internal_sleep_clock = true,
 459		.regs = &wcn6855_regs,
 460		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
 461		.host_ce_config = ath11k_host_ce_config_qca6390,
 462		.ce_count = 9,
 463		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
 464		.target_ce_count = 9,
 465		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
 466		.svc_to_ce_map_len = 14,
 467		.single_pdev_only = true,
 468		.rxdma1_enable = false,
 469		.num_rxmda_per_pdev = 2,
 470		.rx_mac_buf_ring = true,
 471		.vdev_start_delay = true,
 472		.htt_peer_map_v2 = false,
 473
 474		.spectral = {
 475			.fft_sz = 0,
 476			.fft_pad_sz = 0,
 477			.summary_pad_sz = 0,
 478			.fft_hdr_len = 0,
 479			.max_fft_bins = 0,
 480			.fragment_160mhz = false,
 481		},
 482
 483		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 484					BIT(NL80211_IFTYPE_AP),
 485		.supports_monitor = false,
 486		.supports_shadow_regs = true,
 487		.idle_ps = true,
 488		.supports_sta_ps = true,
 489		.cold_boot_calib = false,
 490		.cbcal_restart_fw = false,
 491		.fw_mem_mode = 0,
 492		.num_vdevs = 16 + 1,
 493		.num_peers = 512,
 494		.supports_suspend = true,
 495		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
 496		.supports_regdb = true,
 497		.fix_l1ss = false,
 498		.credit_flow = true,
 499		.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
 500		.hal_params = &ath11k_hw_hal_params_qca6390,
 501		.supports_dynamic_smps_6ghz = false,
 502		.alloc_cacheable_memory = false,
 503		.supports_rssi_stats = true,
 504		.fw_wmi_diag_event = true,
 505		.current_cc_support = true,
 506		.dbr_debug_support = false,
 507		.global_reset = true,
 508		.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
 509		.m3_fw_support = true,
 510		.fixed_bdf_addr = false,
 511		.fixed_mem_region = false,
 512		.static_window_map = false,
 513		.hybrid_bus_type = false,
 514		.fixed_fw_mem = false,
 515		.support_off_channel_tx = true,
 516		.supports_multi_bssid = true,
 517
 518		.sram_dump = {
 519			.start = 0x01400000,
 520			.end = 0x0177ffff,
 521		},
 522
 523		.tcl_ring_retry = true,
 524		.tx_ring_size = DP_TCL_DATA_RING_SIZE,
 525		.smp2p_wow_exit = false,
 526		.support_fw_mac_sequence = true,
 527	},
 528	{
 529		.name = "wcn6750 hw1.0",
 530		.hw_rev = ATH11K_HW_WCN6750_HW10,
 531		.fw = {
 532			.dir = "WCN6750/hw1.0",
 533			.board_size = 256 * 1024,
 534			.cal_offset = 128 * 1024,
 535		},
 536		.max_radios = 1,
 537		.bdf_addr = 0x4B0C0000,
 538		.hw_ops = &wcn6750_ops,
 539		.ring_mask = &ath11k_hw_ring_mask_wcn6750,
 540		.internal_sleep_clock = false,
 541		.regs = &wcn6750_regs,
 542		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750,
 543		.host_ce_config = ath11k_host_ce_config_qca6390,
 544		.ce_count = 9,
 545		.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
 546		.target_ce_count = 9,
 547		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
 548		.svc_to_ce_map_len = 14,
 549		.single_pdev_only = true,
 550		.rxdma1_enable = false,
 551		.num_rxmda_per_pdev = 1,
 552		.rx_mac_buf_ring = true,
 553		.vdev_start_delay = true,
 554		.htt_peer_map_v2 = false,
 555
 556		.spectral = {
 557			.fft_sz = 0,
 558			.fft_pad_sz = 0,
 559			.summary_pad_sz = 0,
 560			.fft_hdr_len = 0,
 561			.max_fft_bins = 0,
 562			.fragment_160mhz = false,
 563		},
 564
 565		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 566					BIT(NL80211_IFTYPE_AP),
 567		.supports_monitor = false,
 568		.supports_shadow_regs = true,
 569		.idle_ps = true,
 570		.supports_sta_ps = true,
 571		.cold_boot_calib = true,
 572		.cbcal_restart_fw = false,
 573		.fw_mem_mode = 0,
 574		.num_vdevs = 16 + 1,
 575		.num_peers = 512,
 576		.supports_suspend = false,
 577		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
 578		.supports_regdb = true,
 579		.fix_l1ss = false,
 580		.credit_flow = true,
 581		.max_tx_ring = DP_TCL_NUM_RING_MAX,
 582		.hal_params = &ath11k_hw_hal_params_wcn6750,
 583		.supports_dynamic_smps_6ghz = false,
 584		.alloc_cacheable_memory = false,
 585		.supports_rssi_stats = true,
 586		.fw_wmi_diag_event = false,
 587		.current_cc_support = true,
 588		.dbr_debug_support = false,
 589		.global_reset = false,
 590		.bios_sar_capa = NULL,
 591		.m3_fw_support = false,
 592		.fixed_bdf_addr = false,
 593		.fixed_mem_region = false,
 594		.static_window_map = true,
 595		.hybrid_bus_type = true,
 596		.fixed_fw_mem = true,
 597		.support_off_channel_tx = true,
 598		.supports_multi_bssid = true,
 599
 600		.sram_dump = {},
 601
 602		.tcl_ring_retry = false,
 603		.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,
 604		.smp2p_wow_exit = true,
 605		.support_fw_mac_sequence = true,
 606	},
 607};
 608
 609static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
 610{
 611	WARN_ON(!ab->hw_params.single_pdev_only);
 612
 613	return &ab->pdevs[0];
 614}
 615
 616void ath11k_fw_stats_pdevs_free(struct list_head *head)
 617{
 618	struct ath11k_fw_stats_pdev *i, *tmp;
 619
 620	list_for_each_entry_safe(i, tmp, head, list) {
 621		list_del(&i->list);
 622		kfree(i);
 623	}
 624}
 625
 626void ath11k_fw_stats_vdevs_free(struct list_head *head)
 627{
 628	struct ath11k_fw_stats_vdev *i, *tmp;
 629
 630	list_for_each_entry_safe(i, tmp, head, list) {
 631		list_del(&i->list);
 632		kfree(i);
 633	}
 634}
 635
 636void ath11k_fw_stats_bcn_free(struct list_head *head)
 637{
 638	struct ath11k_fw_stats_bcn *i, *tmp;
 639
 640	list_for_each_entry_safe(i, tmp, head, list) {
 641		list_del(&i->list);
 642		kfree(i);
 643	}
 644}
 645
 646void ath11k_fw_stats_init(struct ath11k *ar)
 647{
 648	INIT_LIST_HEAD(&ar->fw_stats.pdevs);
 649	INIT_LIST_HEAD(&ar->fw_stats.vdevs);
 650	INIT_LIST_HEAD(&ar->fw_stats.bcn);
 651
 652	init_completion(&ar->fw_stats_complete);
 653}
 654
 655void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)
 656{
 657	ath11k_fw_stats_pdevs_free(&stats->pdevs);
 658	ath11k_fw_stats_vdevs_free(&stats->vdevs);
 659	ath11k_fw_stats_bcn_free(&stats->bcn);
 660}
 661
 662int ath11k_core_suspend(struct ath11k_base *ab)
 663{
 664	int ret;
 665	struct ath11k_pdev *pdev;
 666	struct ath11k *ar;
 667
 668	if (!ab->hw_params.supports_suspend)
 669		return -EOPNOTSUPP;
 670
 671	/* so far single_pdev_only chips have supports_suspend as true
 672	 * and only the first pdev is valid.
 673	 */
 674	pdev = ath11k_core_get_single_pdev(ab);
 675	ar = pdev->ar;
 676	if (!ar || ar->state != ATH11K_STATE_OFF)
 677		return 0;
 678
 679	ret = ath11k_dp_rx_pktlog_stop(ab, true);
 680	if (ret) {
 681		ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
 682			    ret);
 683		return ret;
 684	}
 685
 686	ret = ath11k_mac_wait_tx_complete(ar);
 687	if (ret) {
 688		ath11k_warn(ab, "failed to wait tx complete: %d\n", ret);
 689		return ret;
 690	}
 691
 692	ret = ath11k_wow_enable(ab);
 693	if (ret) {
 694		ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);
 695		return ret;
 696	}
 697
 698	ret = ath11k_dp_rx_pktlog_stop(ab, false);
 699	if (ret) {
 700		ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
 701			    ret);
 702		return ret;
 703	}
 704
 705	ath11k_ce_stop_shadow_timers(ab);
 706	ath11k_dp_stop_shadow_timers(ab);
 707
 708	ath11k_hif_irq_disable(ab);
 709	ath11k_hif_ce_irq_disable(ab);
 710
 711	ret = ath11k_hif_suspend(ab);
 712	if (ret) {
 713		ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
 714		return ret;
 715	}
 716
 717	return 0;
 718}
 719EXPORT_SYMBOL(ath11k_core_suspend);
 720
 721int ath11k_core_resume(struct ath11k_base *ab)
 722{
 723	int ret;
 724	struct ath11k_pdev *pdev;
 725	struct ath11k *ar;
 726
 727	if (!ab->hw_params.supports_suspend)
 728		return -EOPNOTSUPP;
 729
 730	/* so far signle_pdev_only chips have supports_suspend as true
 731	 * and only the first pdev is valid.
 732	 */
 733	pdev = ath11k_core_get_single_pdev(ab);
 734	ar = pdev->ar;
 735	if (!ar || ar->state != ATH11K_STATE_OFF)
 736		return 0;
 737
 738	ret = ath11k_hif_resume(ab);
 739	if (ret) {
 740		ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
 741		return ret;
 742	}
 743
 744	ath11k_hif_ce_irq_enable(ab);
 745	ath11k_hif_irq_enable(ab);
 746
 747	ret = ath11k_dp_rx_pktlog_start(ab);
 748	if (ret) {
 749		ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
 750			    ret);
 751		return ret;
 752	}
 753
 754	ret = ath11k_wow_wakeup(ab);
 755	if (ret) {
 756		ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);
 757		return ret;
 758	}
 759
 760	return 0;
 761}
 762EXPORT_SYMBOL(ath11k_core_resume);
 763
 764static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)
 765{
 766	struct ath11k_base *ab = data;
 767	const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC;
 768	struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr;
 769	ssize_t copied;
 770	size_t len;
 771	int i;
 772
 773	if (ab->qmi.target.bdf_ext[0] != '\0')
 774		return;
 775
 776	if (hdr->type != ATH11K_SMBIOS_BDF_EXT_TYPE)
 777		return;
 778
 779	if (hdr->length != ATH11K_SMBIOS_BDF_EXT_LENGTH) {
 780		ath11k_dbg(ab, ATH11K_DBG_BOOT,
 781			   "wrong smbios bdf ext type length (%d).\n",
 782			   hdr->length);
 783		return;
 784	}
 785
 786	spin_lock_bh(&ab->base_lock);
 787
 788	switch (smbios->country_code_flag) {
 789	case ATH11K_SMBIOS_CC_ISO:
 790		ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff;
 791		ab->new_alpha2[1] = smbios->cc_code & 0xff;
 792		ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios cc_code %c%c\n",
 793			   ab->new_alpha2[0], ab->new_alpha2[1]);
 794		break;
 795	case ATH11K_SMBIOS_CC_WW:
 796		ab->new_alpha2[0] = '0';
 797		ab->new_alpha2[1] = '0';
 798		ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot smbios worldwide regdomain\n");
 799		break;
 800	default:
 801		ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot ignore smbios country code setting %d\n",
 802			   smbios->country_code_flag);
 803		break;
 804	}
 805
 806	spin_unlock_bh(&ab->base_lock);
 807
 808	if (!smbios->bdf_enabled) {
 809		ath11k_dbg(ab, ATH11K_DBG_BOOT, "bdf variant name not found.\n");
 810		return;
 811	}
 812
 813	/* Only one string exists (per spec) */
 814	if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
 815		ath11k_dbg(ab, ATH11K_DBG_BOOT,
 816			   "bdf variant magic does not match.\n");
 817		return;
 818	}
 819
 820	len = min_t(size_t,
 821		    strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
 822	for (i = 0; i < len; i++) {
 823		if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
 824			ath11k_dbg(ab, ATH11K_DBG_BOOT,
 825				   "bdf variant name contains non ascii chars.\n");
 826			return;
 827		}
 828	}
 829
 830	/* Copy extension name without magic prefix */
 831	copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
 832			 sizeof(ab->qmi.target.bdf_ext));
 833	if (copied < 0) {
 834		ath11k_dbg(ab, ATH11K_DBG_BOOT,
 835			   "bdf variant string is longer than the buffer can accommodate\n");
 836		return;
 837	}
 838
 839	ath11k_dbg(ab, ATH11K_DBG_BOOT,
 840		   "found and validated bdf variant smbios_type 0x%x bdf %s\n",
 841		   ATH11K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
 842}
 843
 844int ath11k_core_check_smbios(struct ath11k_base *ab)
 845{
 846	ab->qmi.target.bdf_ext[0] = '\0';
 847	dmi_walk(ath11k_core_check_cc_code_bdfext, ab);
 848
 849	if (ab->qmi.target.bdf_ext[0] == '\0')
 850		return -ENODATA;
 851
 852	return 0;
 853}
 854
 855int ath11k_core_check_dt(struct ath11k_base *ab)
 856{
 857	size_t max_len = sizeof(ab->qmi.target.bdf_ext);
 858	const char *variant = NULL;
 859	struct device_node *node;
 860
 861	node = ab->dev->of_node;
 862	if (!node)
 863		return -ENOENT;
 864
 865	of_property_read_string(node, "qcom,ath11k-calibration-variant",
 866				&variant);
 867	if (!variant)
 868		return -ENODATA;
 869
 870	if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0)
 871		ath11k_dbg(ab, ATH11K_DBG_BOOT,
 872			   "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
 873			    variant);
 874
 875	return 0;
 876}
 877
 878static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
 879					   size_t name_len, bool with_variant)
 880{
 881	/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
 882	char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
 883
 884	if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')
 885		scnprintf(variant, sizeof(variant), ",variant=%s",
 886			  ab->qmi.target.bdf_ext);
 887
 888	switch (ab->id.bdf_search) {
 889	case ATH11K_BDF_SEARCH_BUS_AND_BOARD:
 890		scnprintf(name, name_len,
 891			  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
 892			  ath11k_bus_str(ab->hif.bus),
 893			  ab->id.vendor, ab->id.device,
 894			  ab->id.subsystem_vendor,
 895			  ab->id.subsystem_device,
 896			  ab->qmi.target.chip_id,
 897			  ab->qmi.target.board_id,
 898			  variant);
 899		break;
 900	default:
 901		scnprintf(name, name_len,
 902			  "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
 903			  ath11k_bus_str(ab->hif.bus),
 904			  ab->qmi.target.chip_id,
 905			  ab->qmi.target.board_id, variant);
 906		break;
 907	}
 908
 909	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
 910
 911	return 0;
 912}
 913
 914static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
 915					 size_t name_len)
 916{
 917	return __ath11k_core_create_board_name(ab, name, name_len, true);
 918}
 919
 920static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name,
 921						  size_t name_len)
 922{
 923	return __ath11k_core_create_board_name(ab, name, name_len, false);
 924}
 925
 926const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
 927						    const char *file)
 928{
 929	const struct firmware *fw;
 930	char path[100];
 931	int ret;
 932
 933	if (file == NULL)
 934		return ERR_PTR(-ENOENT);
 935
 936	ath11k_core_create_firmware_path(ab, file, path, sizeof(path));
 937
 938	ret = firmware_request_nowarn(&fw, path, ab->dev);
 939	if (ret)
 940		return ERR_PTR(ret);
 941
 942	ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n",
 943		   path, fw->size);
 944
 945	return fw;
 946}
 947
 948void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
 949{
 950	if (!IS_ERR(bd->fw))
 951		release_firmware(bd->fw);
 952
 953	memset(bd, 0, sizeof(*bd));
 954}
 955
 956static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
 957					 struct ath11k_board_data *bd,
 958					 const void *buf, size_t buf_len,
 959					 const char *boardname,
 960					 int ie_id,
 961					 int name_id,
 962					 int data_id)
 963{
 964	const struct ath11k_fw_ie *hdr;
 965	bool name_match_found;
 966	int ret, board_ie_id;
 967	size_t board_ie_len;
 968	const void *board_ie_data;
 969
 970	name_match_found = false;
 971
 972	/* go through ATH11K_BD_IE_BOARD_/ATH11K_BD_IE_REGDB_ elements */
 973	while (buf_len > sizeof(struct ath11k_fw_ie)) {
 974		hdr = buf;
 975		board_ie_id = le32_to_cpu(hdr->id);
 976		board_ie_len = le32_to_cpu(hdr->len);
 977		board_ie_data = hdr->data;
 978
 979		buf_len -= sizeof(*hdr);
 980		buf += sizeof(*hdr);
 981
 982		if (buf_len < ALIGN(board_ie_len, 4)) {
 983			ath11k_err(ab, "invalid %s length: %zu < %zu\n",
 984				   ath11k_bd_ie_type_str(ie_id),
 985				   buf_len, ALIGN(board_ie_len, 4));
 986			ret = -EINVAL;
 987			goto out;
 988		}
 989
 990		if (board_ie_id == name_id) {
 991			ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "",
 992					board_ie_data, board_ie_len);
 993
 994			if (board_ie_len != strlen(boardname))
 995				goto next;
 996
 997			ret = memcmp(board_ie_data, boardname, strlen(boardname));
 998			if (ret)
 999				goto next;
1000
1001			name_match_found = true;
1002			ath11k_dbg(ab, ATH11K_DBG_BOOT,
1003				   "boot found match %s for name '%s'",
1004				   ath11k_bd_ie_type_str(ie_id),
1005				   boardname);
1006		} else if (board_ie_id == data_id) {
1007			if (!name_match_found)
1008				/* no match found */
1009				goto next;
1010
1011			ath11k_dbg(ab, ATH11K_DBG_BOOT,
1012				   "boot found %s for '%s'",
1013				   ath11k_bd_ie_type_str(ie_id),
1014				   boardname);
1015
1016			bd->data = board_ie_data;
1017			bd->len = board_ie_len;
1018
1019			ret = 0;
1020			goto out;
1021		} else {
1022			ath11k_warn(ab, "unknown %s id found: %d\n",
1023				    ath11k_bd_ie_type_str(ie_id),
1024				    board_ie_id);
1025		}
1026next:
1027		/* jump over the padding */
1028		board_ie_len = ALIGN(board_ie_len, 4);
1029
1030		buf_len -= board_ie_len;
1031		buf += board_ie_len;
1032	}
1033
1034	/* no match found */
1035	ret = -ENOENT;
1036
1037out:
1038	return ret;
1039}
1040
1041static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
1042					      struct ath11k_board_data *bd,
1043					      const char *boardname,
1044					      int ie_id_match,
1045					      int name_id,
1046					      int data_id)
1047{
1048	size_t len, magic_len;
1049	const u8 *data;
1050	char *filename, filepath[100];
1051	size_t ie_len;
1052	struct ath11k_fw_ie *hdr;
1053	int ret, ie_id;
1054
1055	filename = ATH11K_BOARD_API2_FILE;
1056
1057	if (!bd->fw)
1058		bd->fw = ath11k_core_firmware_request(ab, filename);
1059
1060	if (IS_ERR(bd->fw))
1061		return PTR_ERR(bd->fw);
1062
1063	data = bd->fw->data;
1064	len = bd->fw->size;
1065
1066	ath11k_core_create_firmware_path(ab, filename,
1067					 filepath, sizeof(filepath));
1068
1069	/* magic has extra null byte padded */
1070	magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
1071	if (len < magic_len) {
1072		ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
1073			   filepath, len);
1074		ret = -EINVAL;
1075		goto err;
1076	}
1077
1078	if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) {
1079		ath11k_err(ab, "found invalid board magic\n");
1080		ret = -EINVAL;
1081		goto err;
1082	}
1083
1084	/* magic is padded to 4 bytes */
1085	magic_len = ALIGN(magic_len, 4);
1086	if (len < magic_len) {
1087		ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
1088			   filepath, len);
1089		ret = -EINVAL;
1090		goto err;
1091	}
1092
1093	data += magic_len;
1094	len -= magic_len;
1095
1096	while (len > sizeof(struct ath11k_fw_ie)) {
1097		hdr = (struct ath11k_fw_ie *)data;
1098		ie_id = le32_to_cpu(hdr->id);
1099		ie_len = le32_to_cpu(hdr->len);
1100
1101		len -= sizeof(*hdr);
1102		data = hdr->data;
1103
1104		if (len < ALIGN(ie_len, 4)) {
1105			ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
1106				   ie_id, ie_len, len);
1107			ret = -EINVAL;
1108			goto err;
1109		}
1110
1111		if (ie_id == ie_id_match) {
1112			ret = ath11k_core_parse_bd_ie_board(ab, bd, data,
1113							    ie_len,
1114							    boardname,
1115							    ie_id_match,
1116							    name_id,
1117							    data_id);
1118			if (ret == -ENOENT)
1119				/* no match found, continue */
1120				goto next;
1121			else if (ret)
1122				/* there was an error, bail out */
1123				goto err;
1124			/* either found or error, so stop searching */
1125			goto out;
1126		}
1127next:
1128		/* jump over the padding */
1129		ie_len = ALIGN(ie_len, 4);
1130
1131		len -= ie_len;
1132		data += ie_len;
1133	}
1134
1135out:
1136	if (!bd->data || !bd->len) {
1137		ath11k_dbg(ab, ATH11K_DBG_BOOT,
1138			   "failed to fetch %s for %s from %s\n",
1139			   ath11k_bd_ie_type_str(ie_id_match),
1140			   boardname, filepath);
1141		ret = -ENODATA;
1142		goto err;
1143	}
1144
1145	return 0;
1146
1147err:
1148	ath11k_core_free_bdf(ab, bd);
1149	return ret;
1150}
1151
1152int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
1153				       struct ath11k_board_data *bd,
1154				       const char *name)
1155{
1156	bd->fw = ath11k_core_firmware_request(ab, name);
1157
1158	if (IS_ERR(bd->fw))
1159		return PTR_ERR(bd->fw);
1160
1161	bd->data = bd->fw->data;
1162	bd->len = bd->fw->size;
1163
1164	return 0;
1165}
1166
1167#define BOARD_NAME_SIZE 200
1168int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
1169{
1170	char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE];
1171	char *filename, filepath[100];
1172	int ret;
1173
1174	filename = ATH11K_BOARD_API2_FILE;
1175
1176	ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname));
1177	if (ret) {
1178		ath11k_err(ab, "failed to create board name: %d", ret);
1179		return ret;
1180	}
1181
1182	ab->bd_api = 2;
1183	ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,
1184						 ATH11K_BD_IE_BOARD,
1185						 ATH11K_BD_IE_BOARD_NAME,
1186						 ATH11K_BD_IE_BOARD_DATA);
1187	if (!ret)
1188		goto success;
1189
1190	ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname,
1191						     sizeof(fallback_boardname));
1192	if (ret) {
1193		ath11k_err(ab, "failed to create fallback board name: %d", ret);
1194		return ret;
1195	}
1196
1197	ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname,
1198						 ATH11K_BD_IE_BOARD,
1199						 ATH11K_BD_IE_BOARD_NAME,
1200						 ATH11K_BD_IE_BOARD_DATA);
1201	if (!ret)
1202		goto success;
1203
1204	ab->bd_api = 1;
1205	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);
1206	if (ret) {
1207		ath11k_core_create_firmware_path(ab, filename,
1208						 filepath, sizeof(filepath));
1209		ath11k_err(ab, "failed to fetch board data for %s from %s\n",
1210			   boardname, filepath);
1211		if (memcmp(boardname, fallback_boardname, strlen(boardname)))
1212			ath11k_err(ab, "failed to fetch board data for %s from %s\n",
1213				   fallback_boardname, filepath);
1214
1215		ath11k_err(ab, "failed to fetch board.bin from %s\n",
1216			   ab->hw_params.fw.dir);
1217		return ret;
1218	}
1219
1220success:
1221	ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
1222	return 0;
1223}
1224
1225int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)
1226{
1227	char boardname[BOARD_NAME_SIZE];
1228	int ret;
1229
1230	ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
1231	if (ret) {
1232		ath11k_dbg(ab, ATH11K_DBG_BOOT,
1233			   "failed to create board name for regdb: %d", ret);
1234		goto exit;
1235	}
1236
1237	ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,
1238						 ATH11K_BD_IE_REGDB,
1239						 ATH11K_BD_IE_REGDB_NAME,
1240						 ATH11K_BD_IE_REGDB_DATA);
1241	if (!ret)
1242		goto exit;
1243
1244	ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);
1245	if (ret)
1246		ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",
1247			   ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir);
1248
1249exit:
1250	if (!ret)
1251		ath11k_dbg(ab, ATH11K_DBG_BOOT, "fetched regdb\n");
1252
1253	return ret;
1254}
1255
1256static void ath11k_core_stop(struct ath11k_base *ab)
1257{
1258	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
1259		ath11k_qmi_firmware_stop(ab);
1260
1261	ath11k_hif_stop(ab);
1262	ath11k_wmi_detach(ab);
1263	ath11k_dp_pdev_reo_cleanup(ab);
1264
1265	/* De-Init of components as needed */
1266}
1267
1268static int ath11k_core_soc_create(struct ath11k_base *ab)
1269{
1270	int ret;
1271
1272	ret = ath11k_qmi_init_service(ab);
1273	if (ret) {
1274		ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
1275		return ret;
1276	}
1277
1278	ret = ath11k_debugfs_soc_create(ab);
1279	if (ret) {
1280		ath11k_err(ab, "failed to create ath11k debugfs\n");
1281		goto err_qmi_deinit;
1282	}
1283
1284	ret = ath11k_hif_power_up(ab);
1285	if (ret) {
1286		ath11k_err(ab, "failed to power up :%d\n", ret);
1287		goto err_debugfs_reg;
1288	}
1289
1290	return 0;
1291
1292err_debugfs_reg:
1293	ath11k_debugfs_soc_destroy(ab);
1294err_qmi_deinit:
1295	ath11k_qmi_deinit_service(ab);
1296	return ret;
1297}
1298
1299static void ath11k_core_soc_destroy(struct ath11k_base *ab)
1300{
1301	ath11k_debugfs_soc_destroy(ab);
1302	ath11k_dp_free(ab);
1303	ath11k_reg_free(ab);
1304	ath11k_qmi_deinit_service(ab);
1305}
1306
1307static int ath11k_core_pdev_create(struct ath11k_base *ab)
1308{
1309	int ret;
1310
1311	ret = ath11k_debugfs_pdev_create(ab);
1312	if (ret) {
1313		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
1314		return ret;
1315	}
1316
1317	ret = ath11k_dp_pdev_alloc(ab);
1318	if (ret) {
1319		ath11k_err(ab, "failed to attach DP pdev: %d\n", ret);
1320		goto err_pdev_debug;
1321	}
1322
1323	ret = ath11k_mac_register(ab);
1324	if (ret) {
1325		ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
1326		goto err_dp_pdev_free;
1327	}
1328
1329	ret = ath11k_thermal_register(ab);
1330	if (ret) {
1331		ath11k_err(ab, "could not register thermal device: %d\n",
1332			   ret);
1333		goto err_mac_unregister;
1334	}
1335
1336	ret = ath11k_spectral_init(ab);
1337	if (ret) {
1338		ath11k_err(ab, "failed to init spectral %d\n", ret);
1339		goto err_thermal_unregister;
1340	}
1341
1342	return 0;
1343
1344err_thermal_unregister:
1345	ath11k_thermal_unregister(ab);
1346err_mac_unregister:
1347	ath11k_mac_unregister(ab);
1348err_dp_pdev_free:
1349	ath11k_dp_pdev_free(ab);
1350err_pdev_debug:
1351	ath11k_debugfs_pdev_destroy(ab);
1352
1353	return ret;
1354}
1355
1356static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
1357{
1358	ath11k_spectral_deinit(ab);
1359	ath11k_thermal_unregister(ab);
1360	ath11k_mac_unregister(ab);
1361	ath11k_hif_irq_disable(ab);
1362	ath11k_dp_pdev_free(ab);
1363	ath11k_debugfs_pdev_destroy(ab);
1364}
1365
1366static int ath11k_core_start(struct ath11k_base *ab)
1367{
1368	int ret;
1369
1370	ret = ath11k_wmi_attach(ab);
1371	if (ret) {
1372		ath11k_err(ab, "failed to attach wmi: %d\n", ret);
1373		return ret;
1374	}
1375
1376	ret = ath11k_htc_init(ab);
1377	if (ret) {
1378		ath11k_err(ab, "failed to init htc: %d\n", ret);
1379		goto err_wmi_detach;
1380	}
1381
1382	ret = ath11k_hif_start(ab);
1383	if (ret) {
1384		ath11k_err(ab, "failed to start HIF: %d\n", ret);
1385		goto err_wmi_detach;
1386	}
1387
1388	ret = ath11k_htc_wait_target(&ab->htc);
1389	if (ret) {
1390		ath11k_err(ab, "failed to connect to HTC: %d\n", ret);
1391		goto err_hif_stop;
1392	}
1393
1394	ret = ath11k_dp_htt_connect(&ab->dp);
1395	if (ret) {
1396		ath11k_err(ab, "failed to connect to HTT: %d\n", ret);
1397		goto err_hif_stop;
1398	}
1399
1400	ret = ath11k_wmi_connect(ab);
1401	if (ret) {
1402		ath11k_err(ab, "failed to connect wmi: %d\n", ret);
1403		goto err_hif_stop;
1404	}
1405
1406	ret = ath11k_htc_start(&ab->htc);
1407	if (ret) {
1408		ath11k_err(ab, "failed to start HTC: %d\n", ret);
1409		goto err_hif_stop;
1410	}
1411
1412	ret = ath11k_wmi_wait_for_service_ready(ab);
1413	if (ret) {
1414		ath11k_err(ab, "failed to receive wmi service ready event: %d\n",
1415			   ret);
1416		goto err_hif_stop;
1417	}
1418
1419	ret = ath11k_mac_allocate(ab);
1420	if (ret) {
1421		ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n",
1422			   ret);
1423		goto err_hif_stop;
1424	}
1425
1426	ath11k_dp_pdev_pre_alloc(ab);
1427
1428	ret = ath11k_dp_pdev_reo_setup(ab);
1429	if (ret) {
1430		ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
1431		goto err_mac_destroy;
1432	}
1433
1434	ret = ath11k_wmi_cmd_init(ab);
1435	if (ret) {
1436		ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret);
1437		goto err_reo_cleanup;
1438	}
1439
1440	ret = ath11k_wmi_wait_for_unified_ready(ab);
1441	if (ret) {
1442		ath11k_err(ab, "failed to receive wmi unified ready event: %d\n",
1443			   ret);
1444		goto err_reo_cleanup;
1445	}
1446
1447	/* put hardware to DBS mode */
1448	if (ab->hw_params.single_pdev_only && ab->hw_params.num_rxmda_per_pdev > 1) {
1449		ret = ath11k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
1450		if (ret) {
1451			ath11k_err(ab, "failed to send dbs mode: %d\n", ret);
1452			goto err_hif_stop;
1453		}
1454	}
1455
1456	ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);
1457	if (ret) {
1458		ath11k_err(ab, "failed to send htt version request message: %d\n",
1459			   ret);
1460		goto err_reo_cleanup;
1461	}
1462
1463	return 0;
1464
1465err_reo_cleanup:
1466	ath11k_dp_pdev_reo_cleanup(ab);
1467err_mac_destroy:
1468	ath11k_mac_destroy(ab);
1469err_hif_stop:
1470	ath11k_hif_stop(ab);
1471err_wmi_detach:
1472	ath11k_wmi_detach(ab);
1473
1474	return ret;
1475}
1476
1477static int ath11k_core_start_firmware(struct ath11k_base *ab,
1478				      enum ath11k_firmware_mode mode)
1479{
1480	int ret;
1481
1482	ath11k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v2,
1483				    &ab->qmi.ce_cfg.shadow_reg_v2_len);
1484
1485	ret = ath11k_qmi_firmware_start(ab, mode);
1486	if (ret) {
1487		ath11k_err(ab, "failed to send firmware start: %d\n", ret);
1488		return ret;
1489	}
1490
1491	return ret;
1492}
1493
1494int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
1495{
1496	int ret;
1497
1498	ret = ath11k_core_start_firmware(ab, ATH11K_FIRMWARE_MODE_NORMAL);
1499	if (ret) {
1500		ath11k_err(ab, "failed to start firmware: %d\n", ret);
1501		return ret;
1502	}
1503
1504	ret = ath11k_ce_init_pipes(ab);
1505	if (ret) {
1506		ath11k_err(ab, "failed to initialize CE: %d\n", ret);
1507		goto err_firmware_stop;
1508	}
1509
1510	ret = ath11k_dp_alloc(ab);
1511	if (ret) {
1512		ath11k_err(ab, "failed to init DP: %d\n", ret);
1513		goto err_firmware_stop;
1514	}
1515
1516	switch (ath11k_crypto_mode) {
1517	case ATH11K_CRYPT_MODE_SW:
1518		set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1519		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1520		break;
1521	case ATH11K_CRYPT_MODE_HW:
1522		clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
1523		clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1524		break;
1525	default:
1526		ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
1527		return -EINVAL;
1528	}
1529
1530	if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
1531		set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
1532
1533	mutex_lock(&ab->core_lock);
1534	ret = ath11k_core_start(ab);
1535	if (ret) {
1536		ath11k_err(ab, "failed to start core: %d\n", ret);
1537		goto err_dp_free;
1538	}
1539
1540	ret = ath11k_core_pdev_create(ab);
1541	if (ret) {
1542		ath11k_err(ab, "failed to create pdev core: %d\n", ret);
1543		goto err_core_stop;
1544	}
1545	ath11k_hif_irq_enable(ab);
1546	mutex_unlock(&ab->core_lock);
1547
1548	return 0;
1549
1550err_core_stop:
1551	ath11k_core_stop(ab);
1552	ath11k_mac_destroy(ab);
1553err_dp_free:
1554	ath11k_dp_free(ab);
1555	mutex_unlock(&ab->core_lock);
1556err_firmware_stop:
1557	ath11k_qmi_firmware_stop(ab);
1558
1559	return ret;
1560}
1561
1562static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
1563{
1564	int ret;
1565
1566	mutex_lock(&ab->core_lock);
1567	ath11k_thermal_unregister(ab);
1568	ath11k_hif_irq_disable(ab);
1569	ath11k_dp_pdev_free(ab);
1570	ath11k_spectral_deinit(ab);
1571	ath11k_hif_stop(ab);
1572	ath11k_wmi_detach(ab);
1573	ath11k_dp_pdev_reo_cleanup(ab);
1574	mutex_unlock(&ab->core_lock);
1575
1576	ath11k_dp_free(ab);
1577	ath11k_hal_srng_deinit(ab);
1578
1579	ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
1580
1581	ret = ath11k_hal_srng_init(ab);
1582	if (ret)
1583		return ret;
1584
1585	clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
1586
1587	ret = ath11k_core_qmi_firmware_ready(ab);
1588	if (ret)
1589		goto err_hal_srng_deinit;
1590
1591	clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
1592
1593	return 0;
1594
1595err_hal_srng_deinit:
1596	ath11k_hal_srng_deinit(ab);
1597	return ret;
1598}
1599
1600void ath11k_core_halt(struct ath11k *ar)
1601{
1602	struct ath11k_base *ab = ar->ab;
1603
1604	lockdep_assert_held(&ar->conf_mutex);
1605
1606	ar->num_created_vdevs = 0;
1607	ar->allocated_vdev_map = 0;
1608
1609	ath11k_mac_scan_finish(ar);
1610	ath11k_mac_peer_cleanup_all(ar);
1611	cancel_delayed_work_sync(&ar->scan.timeout);
1612	cancel_work_sync(&ar->regd_update_work);
1613	cancel_work_sync(&ab->update_11d_work);
1614
1615	rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
1616	synchronize_rcu();
1617	INIT_LIST_HEAD(&ar->arvifs);
1618	idr_init(&ar->txmgmt_idr);
1619}
1620
1621static void ath11k_update_11d(struct work_struct *work)
1622{
1623	struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
1624	struct ath11k *ar;
1625	struct ath11k_pdev *pdev;
1626	struct wmi_set_current_country_params set_current_param = {};
1627	int ret, i;
1628
1629	spin_lock_bh(&ab->base_lock);
1630	memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);
1631	spin_unlock_bh(&ab->base_lock);
1632
1633	ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",
1634		   set_current_param.alpha2[0],
1635		   set_current_param.alpha2[1]);
1636
1637	for (i = 0; i < ab->num_radios; i++) {
1638		pdev = &ab->pdevs[i];
1639		ar = pdev->ar;
1640
1641		memcpy(&ar->alpha2, &set_current_param.alpha2, 2);
1642		ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
1643		if (ret)
1644			ath11k_warn(ar->ab,
1645				    "pdev id %d failed set current country code: %d\n",
1646				    i, ret);
1647	}
1648}
1649
1650void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)
1651{
1652	struct ath11k *ar;
1653	struct ath11k_pdev *pdev;
1654	int i;
1655
1656	spin_lock_bh(&ab->base_lock);
1657	ab->stats.fw_crash_counter++;
1658	spin_unlock_bh(&ab->base_lock);
1659
1660	for (i = 0; i < ab->num_radios; i++) {
1661		pdev = &ab->pdevs[i];
1662		ar = pdev->ar;
1663		if (!ar || ar->state == ATH11K_STATE_OFF)
1664			continue;
1665
1666		ieee80211_stop_queues(ar->hw);
1667		ath11k_mac_drain_tx(ar);
1668		ar->state_11d = ATH11K_11D_IDLE;
1669		complete(&ar->completed_11d_scan);
1670		complete(&ar->scan.started);
1671		complete_all(&ar->scan.completed);
1672		complete(&ar->scan.on_channel);
1673		complete(&ar->peer_assoc_done);
1674		complete(&ar->peer_delete_done);
1675		complete(&ar->install_key_done);
1676		complete(&ar->vdev_setup_done);
1677		complete(&ar->vdev_delete_done);
1678		complete(&ar->bss_survey_done);
1679		complete(&ar->thermal.wmi_sync);
1680
1681		wake_up(&ar->dp.tx_empty_waitq);
1682		idr_for_each(&ar->txmgmt_idr,
1683			     ath11k_mac_tx_mgmt_pending_free, ar);
1684		idr_destroy(&ar->txmgmt_idr);
1685		wake_up(&ar->txmgmt_empty_waitq);
1686
1687		ar->monitor_vdev_id = -1;
1688		clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);
1689		clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
1690	}
1691
1692	wake_up(&ab->wmi_ab.tx_credits_wq);
1693	wake_up(&ab->peer_mapping_wq);
1694
1695	reinit_completion(&ab->driver_recovery);
1696}
1697
1698static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)
1699{
1700	struct ath11k *ar;
1701	struct ath11k_pdev *pdev;
1702	int i;
1703
1704	for (i = 0; i < ab->num_radios; i++) {
1705		pdev = &ab->pdevs[i];
1706		ar = pdev->ar;
1707		if (!ar || ar->state == ATH11K_STATE_OFF)
1708			continue;
1709
1710		mutex_lock(&ar->conf_mutex);
1711
1712		switch (ar->state) {
1713		case ATH11K_STATE_ON:
1714			ar->state = ATH11K_STATE_RESTARTING;
1715			ath11k_core_halt(ar);
1716			ieee80211_restart_hw(ar->hw);
1717			break;
1718		case ATH11K_STATE_OFF:
1719			ath11k_warn(ab,
1720				    "cannot restart radio %d that hasn't been started\n",
1721				    i);
1722			break;
1723		case ATH11K_STATE_RESTARTING:
1724			break;
1725		case ATH11K_STATE_RESTARTED:
1726			ar->state = ATH11K_STATE_WEDGED;
1727			fallthrough;
1728		case ATH11K_STATE_WEDGED:
1729			ath11k_warn(ab,
1730				    "device is wedged, will not restart radio %d\n", i);
1731			break;
1732		}
1733		mutex_unlock(&ar->conf_mutex);
1734	}
1735	complete(&ab->driver_recovery);
1736}
1737
1738static void ath11k_core_restart(struct work_struct *work)
1739{
1740	struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
1741	int ret;
1742
1743	ret = ath11k_core_reconfigure_on_crash(ab);
1744	if (ret) {
1745		ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
1746		return;
1747	}
1748
1749	if (ab->is_reset)
1750		complete_all(&ab->reconfigure_complete);
1751
1752	if (!ab->is_reset)
1753		ath11k_core_post_reconfigure_recovery(ab);
1754}
1755
1756static void ath11k_core_reset(struct work_struct *work)
1757{
1758	struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work);
1759	int reset_count, fail_cont_count;
1760	long time_left;
1761
1762	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) {
1763		ath11k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags);
1764		return;
1765	}
1766
1767	/* Sometimes the recovery will fail and then the next all recovery fail,
1768	 * this is to avoid infinite recovery since it can not recovery success.
1769	 */
1770	fail_cont_count = atomic_read(&ab->fail_cont_count);
1771
1772	if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FINAL)
1773		return;
1774
1775	if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FIRST &&
1776	    time_before(jiffies, ab->reset_fail_timeout))
1777		return;
1778
1779	reset_count = atomic_inc_return(&ab->reset_count);
1780
1781	if (reset_count > 1) {
1782		/* Sometimes it happened another reset worker before the previous one
1783		 * completed, then the second reset worker will destroy the previous one,
1784		 * thus below is to avoid that.
1785		 */
1786		ath11k_warn(ab, "already resetting count %d\n", reset_count);
1787
1788		reinit_completion(&ab->reset_complete);
1789		time_left = wait_for_completion_timeout(&ab->reset_complete,
1790							ATH11K_RESET_TIMEOUT_HZ);
1791
1792		if (time_left) {
1793			ath11k_dbg(ab, ATH11K_DBG_BOOT, "to skip reset\n");
1794			atomic_dec(&ab->reset_count);
1795			return;
1796		}
1797
1798		ab->reset_fail_timeout = jiffies + ATH11K_RESET_FAIL_TIMEOUT_HZ;
1799		/* Record the continuous recovery fail count when recovery failed*/
1800		atomic_inc(&ab->fail_cont_count);
1801	}
1802
1803	ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset starting\n");
1804
1805	ab->is_reset = true;
1806	atomic_set(&ab->recovery_count, 0);
1807	reinit_completion(&ab->recovery_start);
1808	atomic_set(&ab->recovery_start_count, 0);
1809
1810	ath11k_core_pre_reconfigure_recovery(ab);
1811
1812	reinit_completion(&ab->reconfigure_complete);
1813	ath11k_core_post_reconfigure_recovery(ab);
1814
1815	ath11k_dbg(ab, ATH11K_DBG_BOOT, "waiting recovery start...\n");
1816
1817	time_left = wait_for_completion_timeout(&ab->recovery_start,
1818						ATH11K_RECOVER_START_TIMEOUT_HZ);
1819
1820	ath11k_hif_power_down(ab);
1821	ath11k_hif_power_up(ab);
1822
1823	ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
1824}
1825
1826static int ath11k_init_hw_params(struct ath11k_base *ab)
1827{
1828	const struct ath11k_hw_params *hw_params = NULL;
1829	int i;
1830
1831	for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
1832		hw_params = &ath11k_hw_params[i];
1833
1834		if (hw_params->hw_rev == ab->hw_rev)
1835			break;
1836	}
1837
1838	if (i == ARRAY_SIZE(ath11k_hw_params)) {
1839		ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);
1840		return -EINVAL;
1841	}
1842
1843	ab->hw_params = *hw_params;
1844
1845	ath11k_info(ab, "%s\n", ab->hw_params.name);
1846
1847	return 0;
1848}
1849
1850int ath11k_core_pre_init(struct ath11k_base *ab)
1851{
1852	int ret;
1853
1854	ret = ath11k_init_hw_params(ab);
1855	if (ret) {
1856		ath11k_err(ab, "failed to get hw params: %d\n", ret);
1857		return ret;
1858	}
1859
1860	return 0;
1861}
1862EXPORT_SYMBOL(ath11k_core_pre_init);
1863
1864int ath11k_core_init(struct ath11k_base *ab)
1865{
1866	int ret;
1867
1868	ret = ath11k_core_soc_create(ab);
1869	if (ret) {
1870		ath11k_err(ab, "failed to create soc core: %d\n", ret);
1871		return ret;
1872	}
1873
1874	return 0;
1875}
1876EXPORT_SYMBOL(ath11k_core_init);
1877
1878void ath11k_core_deinit(struct ath11k_base *ab)
1879{
1880	mutex_lock(&ab->core_lock);
1881
1882	ath11k_core_pdev_destroy(ab);
1883	ath11k_core_stop(ab);
1884
1885	mutex_unlock(&ab->core_lock);
1886
1887	ath11k_hif_power_down(ab);
1888	ath11k_mac_destroy(ab);
1889	ath11k_core_soc_destroy(ab);
1890}
1891EXPORT_SYMBOL(ath11k_core_deinit);
1892
1893void ath11k_core_free(struct ath11k_base *ab)
1894{
1895	destroy_workqueue(ab->workqueue_aux);
1896	destroy_workqueue(ab->workqueue);
1897
1898	kfree(ab);
1899}
1900EXPORT_SYMBOL(ath11k_core_free);
1901
1902struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
1903				      enum ath11k_bus bus)
1904{
1905	struct ath11k_base *ab;
1906
1907	ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);
1908	if (!ab)
1909		return NULL;
1910
1911	init_completion(&ab->driver_recovery);
1912
1913	ab->workqueue = create_singlethread_workqueue("ath11k_wq");
1914	if (!ab->workqueue)
1915		goto err_sc_free;
1916
1917	ab->workqueue_aux = create_singlethread_workqueue("ath11k_aux_wq");
1918	if (!ab->workqueue_aux)
1919		goto err_free_wq;
1920
1921	mutex_init(&ab->core_lock);
1922	mutex_init(&ab->tbl_mtx_lock);
1923	spin_lock_init(&ab->base_lock);
1924	mutex_init(&ab->vdev_id_11d_lock);
1925	init_completion(&ab->reset_complete);
1926	init_completion(&ab->reconfigure_complete);
1927	init_completion(&ab->recovery_start);
1928
1929	INIT_LIST_HEAD(&ab->peers);
1930	init_waitqueue_head(&ab->peer_mapping_wq);
1931	init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
1932	init_waitqueue_head(&ab->qmi.cold_boot_waitq);
1933	INIT_WORK(&ab->restart_work, ath11k_core_restart);
1934	INIT_WORK(&ab->update_11d_work, ath11k_update_11d);
1935	INIT_WORK(&ab->reset_work, ath11k_core_reset);
1936	timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
1937	init_completion(&ab->htc_suspend);
1938	init_completion(&ab->wow.wakeup_completed);
1939
1940	ab->dev = dev;
1941	ab->hif.bus = bus;
1942
1943	return ab;
1944
1945err_free_wq:
1946	destroy_workqueue(ab->workqueue);
1947err_sc_free:
1948	kfree(ab);
1949	return NULL;
1950}
1951EXPORT_SYMBOL(ath11k_core_alloc);
1952
1953MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
1954MODULE_LICENSE("Dual BSD/GPL");