1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear 2d5c65159SKalle Valo /* 3d5c65159SKalle Valo * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4d5c65159SKalle Valo */ 5d5c65159SKalle Valo 6d5c65159SKalle Valo #include <linux/module.h> 7d5c65159SKalle Valo #include <linux/slab.h> 8d5c65159SKalle Valo #include <linux/remoteproc.h> 9d5c65159SKalle Valo #include <linux/firmware.h> 10d5c65159SKalle Valo #include "core.h" 11d5c65159SKalle Valo #include "dp_tx.h" 129c57d7e3SVasanthakumar Thiagarajan #include "dp_rx.h" 13d5c65159SKalle Valo #include "debug.h" 1431858805SGovind Singh #include "hif.h" 15d5c65159SKalle Valo 16d5c65159SKalle Valo unsigned int ath11k_debug_mask; 176e0355afSGovind Singh EXPORT_SYMBOL(ath11k_debug_mask); 18d5c65159SKalle Valo module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); 19d5c65159SKalle Valo MODULE_PARM_DESC(debug_mask, "Debugging mask"); 20d5c65159SKalle Valo 21aa2092a9SVenkateswara Naralasetty static unsigned int ath11k_crypto_mode; 22aa2092a9SVenkateswara Naralasetty module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644); 23aa2092a9SVenkateswara Naralasetty MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software"); 24aa2092a9SVenkateswara Naralasetty 25aa2092a9SVenkateswara Naralasetty /* frame mode values are mapped as per enum ath11k_hw_txrx_mode */ 26aa2092a9SVenkateswara Naralasetty unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI; 27aa2092a9SVenkateswara Naralasetty module_param_named(frame_mode, ath11k_frame_mode, uint, 0644); 28aa2092a9SVenkateswara Naralasetty MODULE_PARM_DESC(frame_mode, 29aa2092a9SVenkateswara Naralasetty "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)"); 30aa2092a9SVenkateswara Naralasetty 31d3318abfSAnilkumar Kolli static const struct ath11k_hw_params ath11k_hw_params[] = { 32d3318abfSAnilkumar Kolli { 33d3318abfSAnilkumar Kolli .hw_rev = ATH11K_HW_IPQ8074, 34d3318abfSAnilkumar Kolli .name = "ipq8074 hw2.0", 35d5c65159SKalle Valo .fw = { 3634d9fc80SKalle Valo .dir = "IPQ8074/hw2.0", 37b3a18338SKalle Valo .board_size = 256 * 1024, 38b3a18338SKalle Valo .cal_size = 256 * 1024, 39d5c65159SKalle Valo }, 40b1cc29e9SAnilkumar Kolli .max_radios = 3, 413b94ae4cSAnilkumar Kolli .bdf_addr = 0x4B0C0000, 42d547ca4cSAnilkumar Kolli .hw_ops = &ipq8074_ops, 4334d5a3a8SKalle Valo .ring_mask = &ath11k_hw_ring_mask_ipq8074, 44727fae14SCarl Huang .internal_sleep_clock = false, 456976433cSCarl Huang .regs = &ipq8074_regs, 46e3396b8bSCarl Huang .host_ce_config = ath11k_host_ce_config_ipq8074, 47e3396b8bSCarl Huang .ce_count = 12, 48967c1d11SAnilkumar Kolli .target_ce_config = ath11k_target_ce_config_wlan_ipq8074, 49967c1d11SAnilkumar Kolli .target_ce_count = 11, 50967c1d11SAnilkumar Kolli .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074, 51967c1d11SAnilkumar Kolli .svc_to_ce_map_len = 21, 525f859bc0SCarl Huang .single_pdev_only = false, 53ed0192f7SCarl Huang .needs_band_to_mac = true, 547f6fc1ebSCarl Huang .rxdma1_enable = true, 554152e420SCarl Huang .num_rxmda_per_pdev = 1, 564152e420SCarl Huang .rx_mac_buf_ring = false, 57e7495035SCarl Huang .vdev_start_delay = false, 58a6275302SCarl Huang .htt_peer_map_v2 = true, 59065f5f68SCarl Huang .tcl_0_only = false, 605cca5fa1SKarthikeyan Periyasamy .spectral_fft_sz = 2, 612626c269SKalle Valo 622626c269SKalle Valo .interface_modes = BIT(NL80211_IFTYPE_STATION) | 632626c269SKalle Valo BIT(NL80211_IFTYPE_AP) | 642626c269SKalle Valo BIT(NL80211_IFTYPE_MESH_POINT), 653f6e6c32SKalle Valo .supports_monitor = true, 66e838c14aSCarl Huang .supports_shadow_regs = false, 67*c83c500bSCarl Huang .idle_ps = false, 68d3318abfSAnilkumar Kolli }, 699de2ad43SCarl Huang { 70b129699aSAnilkumar Kolli .hw_rev = ATH11K_HW_IPQ6018_HW10, 71b129699aSAnilkumar Kolli .name = "ipq6018 hw1.0", 72b129699aSAnilkumar Kolli .fw = { 73b129699aSAnilkumar Kolli .dir = "IPQ6018/hw1.0", 74b129699aSAnilkumar Kolli .board_size = 256 * 1024, 75b129699aSAnilkumar Kolli .cal_size = 256 * 1024, 76b129699aSAnilkumar Kolli }, 77b129699aSAnilkumar Kolli .max_radios = 2, 78b129699aSAnilkumar Kolli .bdf_addr = 0x4ABC0000, 79b129699aSAnilkumar Kolli .hw_ops = &ipq6018_ops, 80b129699aSAnilkumar Kolli .ring_mask = &ath11k_hw_ring_mask_ipq8074, 81b129699aSAnilkumar Kolli .internal_sleep_clock = false, 82b129699aSAnilkumar Kolli .regs = &ipq8074_regs, 83b129699aSAnilkumar Kolli .host_ce_config = ath11k_host_ce_config_ipq8074, 84b129699aSAnilkumar Kolli .ce_count = 12, 85b129699aSAnilkumar Kolli .target_ce_config = ath11k_target_ce_config_wlan_ipq8074, 86b129699aSAnilkumar Kolli .target_ce_count = 11, 87b129699aSAnilkumar Kolli .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018, 88b129699aSAnilkumar Kolli .svc_to_ce_map_len = 19, 89b129699aSAnilkumar Kolli .single_pdev_only = false, 90b129699aSAnilkumar Kolli .needs_band_to_mac = true, 91b129699aSAnilkumar Kolli .rxdma1_enable = true, 92b129699aSAnilkumar Kolli .num_rxmda_per_pdev = 1, 93b129699aSAnilkumar Kolli .rx_mac_buf_ring = false, 94b129699aSAnilkumar Kolli .vdev_start_delay = false, 95b129699aSAnilkumar Kolli .htt_peer_map_v2 = true, 96b129699aSAnilkumar Kolli .tcl_0_only = false, 975cca5fa1SKarthikeyan Periyasamy .spectral_fft_sz = 4, 982626c269SKalle Valo 992626c269SKalle Valo .interface_modes = BIT(NL80211_IFTYPE_STATION) | 1002626c269SKalle Valo BIT(NL80211_IFTYPE_AP) | 1012626c269SKalle Valo BIT(NL80211_IFTYPE_MESH_POINT), 1023f6e6c32SKalle Valo .supports_monitor = true, 103e838c14aSCarl Huang .supports_shadow_regs = false, 104*c83c500bSCarl Huang .idle_ps = false, 105b129699aSAnilkumar Kolli }, 106b129699aSAnilkumar Kolli { 1079de2ad43SCarl Huang .name = "qca6390 hw2.0", 1089de2ad43SCarl Huang .hw_rev = ATH11K_HW_QCA6390_HW20, 1099de2ad43SCarl Huang .fw = { 1109de2ad43SCarl Huang .dir = "QCA6390/hw2.0", 1119de2ad43SCarl Huang .board_size = 256 * 1024, 1129de2ad43SCarl Huang .cal_size = 256 * 1024, 1139de2ad43SCarl Huang }, 1149de2ad43SCarl Huang .max_radios = 3, 1159de2ad43SCarl Huang .bdf_addr = 0x4B0C0000, 1169de2ad43SCarl Huang .hw_ops = &qca6390_ops, 117d4ecb90bSCarl Huang .ring_mask = &ath11k_hw_ring_mask_qca6390, 118727fae14SCarl Huang .internal_sleep_clock = true, 1196976433cSCarl Huang .regs = &qca6390_regs, 120e3396b8bSCarl Huang .host_ce_config = ath11k_host_ce_config_qca6390, 121e3396b8bSCarl Huang .ce_count = 9, 122967c1d11SAnilkumar Kolli .target_ce_config = ath11k_target_ce_config_wlan_qca6390, 123967c1d11SAnilkumar Kolli .target_ce_count = 9, 124967c1d11SAnilkumar Kolli .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390, 125967c1d11SAnilkumar Kolli .svc_to_ce_map_len = 14, 1265f859bc0SCarl Huang .single_pdev_only = true, 127ed0192f7SCarl Huang .needs_band_to_mac = false, 1287f6fc1ebSCarl Huang .rxdma1_enable = false, 1294152e420SCarl Huang .num_rxmda_per_pdev = 2, 1304152e420SCarl Huang .rx_mac_buf_ring = true, 131e7495035SCarl Huang .vdev_start_delay = true, 132a6275302SCarl Huang .htt_peer_map_v2 = false, 133065f5f68SCarl Huang .tcl_0_only = true, 1345cca5fa1SKarthikeyan Periyasamy .spectral_fft_sz = 0, 1352626c269SKalle Valo 1362626c269SKalle Valo .interface_modes = BIT(NL80211_IFTYPE_STATION) | 1372626c269SKalle Valo BIT(NL80211_IFTYPE_AP), 1383f6e6c32SKalle Valo .supports_monitor = false, 139e838c14aSCarl Huang .supports_shadow_regs = true, 140*c83c500bSCarl Huang .idle_ps = true, 1419de2ad43SCarl Huang }, 142d5c65159SKalle Valo }; 143d5c65159SKalle Valo 144d5c65159SKalle Valo static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, 145d5c65159SKalle Valo size_t name_len) 146d5c65159SKalle Valo { 147d5c65159SKalle Valo scnprintf(name, name_len, 1486eb6ea51SGovind Singh "bus=%s,qmi-chip-id=%d,qmi-board-id=%d", 1496eb6ea51SGovind Singh ath11k_bus_str(ab->hif.bus), 150d5c65159SKalle Valo ab->qmi.target.chip_id, 151d5c65159SKalle Valo ab->qmi.target.board_id); 152d5c65159SKalle Valo 153d5c65159SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name); 154d5c65159SKalle Valo 155d5c65159SKalle Valo return 0; 156d5c65159SKalle Valo } 157d5c65159SKalle Valo 1587b57b2ddSKalle Valo const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, 159d5c65159SKalle Valo const char *file) 160d5c65159SKalle Valo { 161d5c65159SKalle Valo const struct firmware *fw; 16234d9fc80SKalle Valo char path[100]; 163d5c65159SKalle Valo int ret; 164d5c65159SKalle Valo 165d5c65159SKalle Valo if (file == NULL) 166d5c65159SKalle Valo return ERR_PTR(-ENOENT); 167d5c65159SKalle Valo 16834d9fc80SKalle Valo ath11k_core_create_firmware_path(ab, file, path, sizeof(path)); 169d5c65159SKalle Valo 17034d9fc80SKalle Valo ret = firmware_request_nowarn(&fw, path, ab->dev); 171d5c65159SKalle Valo if (ret) 172d5c65159SKalle Valo return ERR_PTR(ret); 1737b57b2ddSKalle Valo 1747b57b2ddSKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n", 17534d9fc80SKalle Valo path, fw->size); 176d5c65159SKalle Valo 177d5c65159SKalle Valo return fw; 178d5c65159SKalle Valo } 179d5c65159SKalle Valo 180d5c65159SKalle Valo void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) 181d5c65159SKalle Valo { 182d5c65159SKalle Valo if (!IS_ERR(bd->fw)) 183d5c65159SKalle Valo release_firmware(bd->fw); 184d5c65159SKalle Valo 185d5c65159SKalle Valo memset(bd, 0, sizeof(*bd)); 186d5c65159SKalle Valo } 187d5c65159SKalle Valo 188d5c65159SKalle Valo static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, 189d5c65159SKalle Valo struct ath11k_board_data *bd, 190d5c65159SKalle Valo const void *buf, size_t buf_len, 191d5c65159SKalle Valo const char *boardname, 192d5c65159SKalle Valo int bd_ie_type) 193d5c65159SKalle Valo { 194d5c65159SKalle Valo const struct ath11k_fw_ie *hdr; 195d5c65159SKalle Valo bool name_match_found; 196d5c65159SKalle Valo int ret, board_ie_id; 197d5c65159SKalle Valo size_t board_ie_len; 198d5c65159SKalle Valo const void *board_ie_data; 199d5c65159SKalle Valo 200d5c65159SKalle Valo name_match_found = false; 201d5c65159SKalle Valo 202d5c65159SKalle Valo /* go through ATH11K_BD_IE_BOARD_ elements */ 203d5c65159SKalle Valo while (buf_len > sizeof(struct ath11k_fw_ie)) { 204d5c65159SKalle Valo hdr = buf; 205d5c65159SKalle Valo board_ie_id = le32_to_cpu(hdr->id); 206d5c65159SKalle Valo board_ie_len = le32_to_cpu(hdr->len); 207d5c65159SKalle Valo board_ie_data = hdr->data; 208d5c65159SKalle Valo 209d5c65159SKalle Valo buf_len -= sizeof(*hdr); 210d5c65159SKalle Valo buf += sizeof(*hdr); 211d5c65159SKalle Valo 212d5c65159SKalle Valo if (buf_len < ALIGN(board_ie_len, 4)) { 213d5c65159SKalle Valo ath11k_err(ab, "invalid ATH11K_BD_IE_BOARD length: %zu < %zu\n", 214d5c65159SKalle Valo buf_len, ALIGN(board_ie_len, 4)); 215d5c65159SKalle Valo ret = -EINVAL; 216d5c65159SKalle Valo goto out; 217d5c65159SKalle Valo } 218d5c65159SKalle Valo 219d5c65159SKalle Valo switch (board_ie_id) { 220d5c65159SKalle Valo case ATH11K_BD_IE_BOARD_NAME: 221d5c65159SKalle Valo ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "", 222d5c65159SKalle Valo board_ie_data, board_ie_len); 223d5c65159SKalle Valo 224d5c65159SKalle Valo if (board_ie_len != strlen(boardname)) 225d5c65159SKalle Valo break; 226d5c65159SKalle Valo 227d5c65159SKalle Valo ret = memcmp(board_ie_data, boardname, strlen(boardname)); 228d5c65159SKalle Valo if (ret) 229d5c65159SKalle Valo break; 230d5c65159SKalle Valo 231d5c65159SKalle Valo name_match_found = true; 232d5c65159SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, 233d5c65159SKalle Valo "boot found match for name '%s'", 234d5c65159SKalle Valo boardname); 235d5c65159SKalle Valo break; 236d5c65159SKalle Valo case ATH11K_BD_IE_BOARD_DATA: 237d5c65159SKalle Valo if (!name_match_found) 238d5c65159SKalle Valo /* no match found */ 239d5c65159SKalle Valo break; 240d5c65159SKalle Valo 241d5c65159SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, 242d5c65159SKalle Valo "boot found board data for '%s'", boardname); 243d5c65159SKalle Valo 244d5c65159SKalle Valo bd->data = board_ie_data; 245d5c65159SKalle Valo bd->len = board_ie_len; 246d5c65159SKalle Valo 247d5c65159SKalle Valo ret = 0; 248d5c65159SKalle Valo goto out; 249d5c65159SKalle Valo default: 250d5c65159SKalle Valo ath11k_warn(ab, "unknown ATH11K_BD_IE_BOARD found: %d\n", 251d5c65159SKalle Valo board_ie_id); 252d5c65159SKalle Valo break; 253d5c65159SKalle Valo } 254d5c65159SKalle Valo 255d5c65159SKalle Valo /* jump over the padding */ 256d5c65159SKalle Valo board_ie_len = ALIGN(board_ie_len, 4); 257d5c65159SKalle Valo 258d5c65159SKalle Valo buf_len -= board_ie_len; 259d5c65159SKalle Valo buf += board_ie_len; 260d5c65159SKalle Valo } 261d5c65159SKalle Valo 262d5c65159SKalle Valo /* no match found */ 263d5c65159SKalle Valo ret = -ENOENT; 264d5c65159SKalle Valo 265d5c65159SKalle Valo out: 266d5c65159SKalle Valo return ret; 267d5c65159SKalle Valo } 268d5c65159SKalle Valo 269d5c65159SKalle Valo static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, 270d5c65159SKalle Valo struct ath11k_board_data *bd, 271d5c65159SKalle Valo const char *boardname) 272d5c65159SKalle Valo { 273d5c65159SKalle Valo size_t len, magic_len; 274d5c65159SKalle Valo const u8 *data; 27531d78a3dSKalle Valo char *filename, filepath[100]; 276d5c65159SKalle Valo size_t ie_len; 277d5c65159SKalle Valo struct ath11k_fw_ie *hdr; 278d5c65159SKalle Valo int ret, ie_id; 279d5c65159SKalle Valo 28031d78a3dSKalle Valo filename = ATH11K_BOARD_API2_FILE; 28131d78a3dSKalle Valo 282d5c65159SKalle Valo if (!bd->fw) 28334d9fc80SKalle Valo bd->fw = ath11k_core_firmware_request(ab, filename); 28434d9fc80SKalle Valo 285d5c65159SKalle Valo if (IS_ERR(bd->fw)) 286d5c65159SKalle Valo return PTR_ERR(bd->fw); 287d5c65159SKalle Valo 288d5c65159SKalle Valo data = bd->fw->data; 289d5c65159SKalle Valo len = bd->fw->size; 290d5c65159SKalle Valo 29131d78a3dSKalle Valo ath11k_core_create_firmware_path(ab, filename, 29231d78a3dSKalle Valo filepath, sizeof(filepath)); 29331d78a3dSKalle Valo 294d5c65159SKalle Valo /* magic has extra null byte padded */ 295d5c65159SKalle Valo magic_len = strlen(ATH11K_BOARD_MAGIC) + 1; 296d5c65159SKalle Valo if (len < magic_len) { 29731d78a3dSKalle Valo ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n", 29831d78a3dSKalle Valo filepath, len); 299d5c65159SKalle Valo ret = -EINVAL; 300d5c65159SKalle Valo goto err; 301d5c65159SKalle Valo } 302d5c65159SKalle Valo 303d5c65159SKalle Valo if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) { 304d5c65159SKalle Valo ath11k_err(ab, "found invalid board magic\n"); 305d5c65159SKalle Valo ret = -EINVAL; 306d5c65159SKalle Valo goto err; 307d5c65159SKalle Valo } 308d5c65159SKalle Valo 309d5c65159SKalle Valo /* magic is padded to 4 bytes */ 310d5c65159SKalle Valo magic_len = ALIGN(magic_len, 4); 311d5c65159SKalle Valo if (len < magic_len) { 31231d78a3dSKalle Valo ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n", 31331d78a3dSKalle Valo filepath, len); 314d5c65159SKalle Valo ret = -EINVAL; 315d5c65159SKalle Valo goto err; 316d5c65159SKalle Valo } 317d5c65159SKalle Valo 318d5c65159SKalle Valo data += magic_len; 319d5c65159SKalle Valo len -= magic_len; 320d5c65159SKalle Valo 321d5c65159SKalle Valo while (len > sizeof(struct ath11k_fw_ie)) { 322d5c65159SKalle Valo hdr = (struct ath11k_fw_ie *)data; 323d5c65159SKalle Valo ie_id = le32_to_cpu(hdr->id); 324d5c65159SKalle Valo ie_len = le32_to_cpu(hdr->len); 325d5c65159SKalle Valo 326d5c65159SKalle Valo len -= sizeof(*hdr); 327d5c65159SKalle Valo data = hdr->data; 328d5c65159SKalle Valo 329d5c65159SKalle Valo if (len < ALIGN(ie_len, 4)) { 330d5c65159SKalle Valo ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n", 331d5c65159SKalle Valo ie_id, ie_len, len); 332d5c65159SKalle Valo return -EINVAL; 333d5c65159SKalle Valo } 334d5c65159SKalle Valo 335d5c65159SKalle Valo switch (ie_id) { 336d5c65159SKalle Valo case ATH11K_BD_IE_BOARD: 337d5c65159SKalle Valo ret = ath11k_core_parse_bd_ie_board(ab, bd, data, 338d5c65159SKalle Valo ie_len, 339d5c65159SKalle Valo boardname, 340d5c65159SKalle Valo ATH11K_BD_IE_BOARD); 341d5c65159SKalle Valo if (ret == -ENOENT) 342d5c65159SKalle Valo /* no match found, continue */ 343d5c65159SKalle Valo break; 344d5c65159SKalle Valo else if (ret) 345d5c65159SKalle Valo /* there was an error, bail out */ 346d5c65159SKalle Valo goto err; 347d5c65159SKalle Valo /* either found or error, so stop searching */ 348d5c65159SKalle Valo goto out; 349d5c65159SKalle Valo } 350d5c65159SKalle Valo 351d5c65159SKalle Valo /* jump over the padding */ 352d5c65159SKalle Valo ie_len = ALIGN(ie_len, 4); 353d5c65159SKalle Valo 354d5c65159SKalle Valo len -= ie_len; 355d5c65159SKalle Valo data += ie_len; 356d5c65159SKalle Valo } 357d5c65159SKalle Valo 358d5c65159SKalle Valo out: 359d5c65159SKalle Valo if (!bd->data || !bd->len) { 360d5c65159SKalle Valo ath11k_err(ab, 36131d78a3dSKalle Valo "failed to fetch board data for %s from %s\n", 36231d78a3dSKalle Valo boardname, filepath); 363d5c65159SKalle Valo ret = -ENODATA; 364d5c65159SKalle Valo goto err; 365d5c65159SKalle Valo } 366d5c65159SKalle Valo 367d5c65159SKalle Valo return 0; 368d5c65159SKalle Valo 369d5c65159SKalle Valo err: 370d5c65159SKalle Valo ath11k_core_free_bdf(ab, bd); 371d5c65159SKalle Valo return ret; 372d5c65159SKalle Valo } 373d5c65159SKalle Valo 374d5c65159SKalle Valo static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, 375d5c65159SKalle Valo struct ath11k_board_data *bd) 376d5c65159SKalle Valo { 37734d9fc80SKalle Valo bd->fw = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_BOARD_FILE); 378d5c65159SKalle Valo if (IS_ERR(bd->fw)) 379d5c65159SKalle Valo return PTR_ERR(bd->fw); 380d5c65159SKalle Valo 381d5c65159SKalle Valo bd->data = bd->fw->data; 382d5c65159SKalle Valo bd->len = bd->fw->size; 383d5c65159SKalle Valo 384d5c65159SKalle Valo return 0; 385d5c65159SKalle Valo } 386d5c65159SKalle Valo 387d5c65159SKalle Valo #define BOARD_NAME_SIZE 100 388d5c65159SKalle Valo int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) 389d5c65159SKalle Valo { 390d5c65159SKalle Valo char boardname[BOARD_NAME_SIZE]; 391d5c65159SKalle Valo int ret; 392d5c65159SKalle Valo 393d5c65159SKalle Valo ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); 394d5c65159SKalle Valo if (ret) { 395d5c65159SKalle Valo ath11k_err(ab, "failed to create board name: %d", ret); 396d5c65159SKalle Valo return ret; 397d5c65159SKalle Valo } 398d5c65159SKalle Valo 399d5c65159SKalle Valo ab->bd_api = 2; 400d5c65159SKalle Valo ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname); 401d5c65159SKalle Valo if (!ret) 402d5c65159SKalle Valo goto success; 403d5c65159SKalle Valo 404d5c65159SKalle Valo ab->bd_api = 1; 405d5c65159SKalle Valo ret = ath11k_core_fetch_board_data_api_1(ab, bd); 406d5c65159SKalle Valo if (ret) { 407d5c65159SKalle Valo ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n", 408d5c65159SKalle Valo ab->hw_params.fw.dir); 409d5c65159SKalle Valo return ret; 410d5c65159SKalle Valo } 411d5c65159SKalle Valo 412d5c65159SKalle Valo success: 413d5c65159SKalle Valo ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api); 414d5c65159SKalle Valo return 0; 415d5c65159SKalle Valo } 416d5c65159SKalle Valo 417d5c65159SKalle Valo static void ath11k_core_stop(struct ath11k_base *ab) 418d5c65159SKalle Valo { 419d5c65159SKalle Valo if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) 420d5c65159SKalle Valo ath11k_qmi_firmware_stop(ab); 421e838c14aSCarl Huang 42231858805SGovind Singh ath11k_hif_stop(ab); 423d5c65159SKalle Valo ath11k_wmi_detach(ab); 4249c57d7e3SVasanthakumar Thiagarajan ath11k_dp_pdev_reo_cleanup(ab); 425d5c65159SKalle Valo 426d5c65159SKalle Valo /* De-Init of components as needed */ 427d5c65159SKalle Valo } 428d5c65159SKalle Valo 429d5c65159SKalle Valo static int ath11k_core_soc_create(struct ath11k_base *ab) 430d5c65159SKalle Valo { 431d5c65159SKalle Valo int ret; 432d5c65159SKalle Valo 433d5c65159SKalle Valo ret = ath11k_qmi_init_service(ab); 434d5c65159SKalle Valo if (ret) { 435d5c65159SKalle Valo ath11k_err(ab, "failed to initialize qmi :%d\n", ret); 436d5c65159SKalle Valo return ret; 437d5c65159SKalle Valo } 438d5c65159SKalle Valo 439cb4e57dbSKalle Valo ret = ath11k_debugfs_soc_create(ab); 440d5c65159SKalle Valo if (ret) { 441d5c65159SKalle Valo ath11k_err(ab, "failed to create ath11k debugfs\n"); 442d5c65159SKalle Valo goto err_qmi_deinit; 443d5c65159SKalle Valo } 444d5c65159SKalle Valo 44531858805SGovind Singh ret = ath11k_hif_power_up(ab); 446d5c65159SKalle Valo if (ret) { 447d5c65159SKalle Valo ath11k_err(ab, "failed to power up :%d\n", ret); 448d5c65159SKalle Valo goto err_debugfs_reg; 449d5c65159SKalle Valo } 450d5c65159SKalle Valo 451d5c65159SKalle Valo return 0; 452d5c65159SKalle Valo 453d5c65159SKalle Valo err_debugfs_reg: 454cb4e57dbSKalle Valo ath11k_debugfs_soc_destroy(ab); 455d5c65159SKalle Valo err_qmi_deinit: 456d5c65159SKalle Valo ath11k_qmi_deinit_service(ab); 457d5c65159SKalle Valo return ret; 458d5c65159SKalle Valo } 459d5c65159SKalle Valo 460d5c65159SKalle Valo static void ath11k_core_soc_destroy(struct ath11k_base *ab) 461d5c65159SKalle Valo { 462cb4e57dbSKalle Valo ath11k_debugfs_soc_destroy(ab); 463d5c65159SKalle Valo ath11k_dp_free(ab); 464d5c65159SKalle Valo ath11k_reg_free(ab); 465d5c65159SKalle Valo ath11k_qmi_deinit_service(ab); 466d5c65159SKalle Valo } 467d5c65159SKalle Valo 468d5c65159SKalle Valo static int ath11k_core_pdev_create(struct ath11k_base *ab) 469d5c65159SKalle Valo { 470d5c65159SKalle Valo int ret; 471d5c65159SKalle Valo 472cb4e57dbSKalle Valo ret = ath11k_debugfs_pdev_create(ab); 473d5c65159SKalle Valo if (ret) { 474d5c65159SKalle Valo ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret); 475d5c65159SKalle Valo return ret; 476d5c65159SKalle Valo } 477d5c65159SKalle Valo 4780366f426SVasanthakumar Thiagarajan ret = ath11k_mac_register(ab); 479d5c65159SKalle Valo if (ret) { 4800366f426SVasanthakumar Thiagarajan ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret); 481d5c65159SKalle Valo goto err_pdev_debug; 482d5c65159SKalle Valo } 483d5c65159SKalle Valo 484d5c65159SKalle Valo ret = ath11k_dp_pdev_alloc(ab); 485d5c65159SKalle Valo if (ret) { 486d5c65159SKalle Valo ath11k_err(ab, "failed to attach DP pdev: %d\n", ret); 4870366f426SVasanthakumar Thiagarajan goto err_mac_unregister; 488d5c65159SKalle Valo } 489d5c65159SKalle Valo 4902a63bbcaSPradeep Kumar Chitrapu ret = ath11k_thermal_register(ab); 4912a63bbcaSPradeep Kumar Chitrapu if (ret) { 4922a63bbcaSPradeep Kumar Chitrapu ath11k_err(ab, "could not register thermal device: %d\n", 4932a63bbcaSPradeep Kumar Chitrapu ret); 4942a63bbcaSPradeep Kumar Chitrapu goto err_dp_pdev_free; 4952a63bbcaSPradeep Kumar Chitrapu } 4962a63bbcaSPradeep Kumar Chitrapu 4979d11b7bfSKarthikeyan Periyasamy ret = ath11k_spectral_init(ab); 4989d11b7bfSKarthikeyan Periyasamy if (ret) { 4999d11b7bfSKarthikeyan Periyasamy ath11k_err(ab, "failed to init spectral %d\n", ret); 5009d11b7bfSKarthikeyan Periyasamy goto err_thermal_unregister; 5019d11b7bfSKarthikeyan Periyasamy } 5029d11b7bfSKarthikeyan Periyasamy 503d5c65159SKalle Valo return 0; 504d5c65159SKalle Valo 5059d11b7bfSKarthikeyan Periyasamy err_thermal_unregister: 5069d11b7bfSKarthikeyan Periyasamy ath11k_thermal_unregister(ab); 5072a63bbcaSPradeep Kumar Chitrapu err_dp_pdev_free: 5082a63bbcaSPradeep Kumar Chitrapu ath11k_dp_pdev_free(ab); 5090366f426SVasanthakumar Thiagarajan err_mac_unregister: 5100366f426SVasanthakumar Thiagarajan ath11k_mac_unregister(ab); 511d5c65159SKalle Valo err_pdev_debug: 512cb4e57dbSKalle Valo ath11k_debugfs_pdev_destroy(ab); 513d5c65159SKalle Valo 514d5c65159SKalle Valo return ret; 515d5c65159SKalle Valo } 516d5c65159SKalle Valo 517d5c65159SKalle Valo static void ath11k_core_pdev_destroy(struct ath11k_base *ab) 518d5c65159SKalle Valo { 5199d11b7bfSKarthikeyan Periyasamy ath11k_spectral_deinit(ab); 5202a63bbcaSPradeep Kumar Chitrapu ath11k_thermal_unregister(ab); 521d5c65159SKalle Valo ath11k_mac_unregister(ab); 52231858805SGovind Singh ath11k_hif_irq_disable(ab); 523d5c65159SKalle Valo ath11k_dp_pdev_free(ab); 524cb4e57dbSKalle Valo ath11k_debugfs_pdev_destroy(ab); 525d5c65159SKalle Valo } 526d5c65159SKalle Valo 527d5c65159SKalle Valo static int ath11k_core_start(struct ath11k_base *ab, 528d5c65159SKalle Valo enum ath11k_firmware_mode mode) 529d5c65159SKalle Valo { 530d5c65159SKalle Valo int ret; 531d5c65159SKalle Valo 532d5c65159SKalle Valo ret = ath11k_qmi_firmware_start(ab, mode); 533d5c65159SKalle Valo if (ret) { 534d5c65159SKalle Valo ath11k_err(ab, "failed to attach wmi: %d\n", ret); 535d5c65159SKalle Valo return ret; 536d5c65159SKalle Valo } 537d5c65159SKalle Valo 538d5c65159SKalle Valo ret = ath11k_wmi_attach(ab); 539d5c65159SKalle Valo if (ret) { 540d5c65159SKalle Valo ath11k_err(ab, "failed to attach wmi: %d\n", ret); 541d5c65159SKalle Valo goto err_firmware_stop; 542d5c65159SKalle Valo } 543d5c65159SKalle Valo 544d5c65159SKalle Valo ret = ath11k_htc_init(ab); 545d5c65159SKalle Valo if (ret) { 546d5c65159SKalle Valo ath11k_err(ab, "failed to init htc: %d\n", ret); 547d5c65159SKalle Valo goto err_wmi_detach; 548d5c65159SKalle Valo } 549d5c65159SKalle Valo 55031858805SGovind Singh ret = ath11k_hif_start(ab); 551d5c65159SKalle Valo if (ret) { 552d5c65159SKalle Valo ath11k_err(ab, "failed to start HIF: %d\n", ret); 553d5c65159SKalle Valo goto err_wmi_detach; 554d5c65159SKalle Valo } 555d5c65159SKalle Valo 556d5c65159SKalle Valo ret = ath11k_htc_wait_target(&ab->htc); 557d5c65159SKalle Valo if (ret) { 558d5c65159SKalle Valo ath11k_err(ab, "failed to connect to HTC: %d\n", ret); 559d5c65159SKalle Valo goto err_hif_stop; 560d5c65159SKalle Valo } 561d5c65159SKalle Valo 562d5c65159SKalle Valo ret = ath11k_dp_htt_connect(&ab->dp); 563d5c65159SKalle Valo if (ret) { 564d5c65159SKalle Valo ath11k_err(ab, "failed to connect to HTT: %d\n", ret); 565d5c65159SKalle Valo goto err_hif_stop; 566d5c65159SKalle Valo } 567d5c65159SKalle Valo 568d5c65159SKalle Valo ret = ath11k_wmi_connect(ab); 569d5c65159SKalle Valo if (ret) { 570d5c65159SKalle Valo ath11k_err(ab, "failed to connect wmi: %d\n", ret); 571d5c65159SKalle Valo goto err_hif_stop; 572d5c65159SKalle Valo } 573d5c65159SKalle Valo 574d5c65159SKalle Valo ret = ath11k_htc_start(&ab->htc); 575d5c65159SKalle Valo if (ret) { 576d5c65159SKalle Valo ath11k_err(ab, "failed to start HTC: %d\n", ret); 577d5c65159SKalle Valo goto err_hif_stop; 578d5c65159SKalle Valo } 579d5c65159SKalle Valo 580d5c65159SKalle Valo ret = ath11k_wmi_wait_for_service_ready(ab); 581d5c65159SKalle Valo if (ret) { 582d5c65159SKalle Valo ath11k_err(ab, "failed to receive wmi service ready event: %d\n", 583d5c65159SKalle Valo ret); 584d5c65159SKalle Valo goto err_hif_stop; 585d5c65159SKalle Valo } 586d5c65159SKalle Valo 5870366f426SVasanthakumar Thiagarajan ret = ath11k_mac_allocate(ab); 5880366f426SVasanthakumar Thiagarajan if (ret) { 5890366f426SVasanthakumar Thiagarajan ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n", 5900366f426SVasanthakumar Thiagarajan ret); 5910366f426SVasanthakumar Thiagarajan goto err_hif_stop; 5920366f426SVasanthakumar Thiagarajan } 5930366f426SVasanthakumar Thiagarajan 5949c57d7e3SVasanthakumar Thiagarajan ath11k_dp_pdev_pre_alloc(ab); 5959c57d7e3SVasanthakumar Thiagarajan 5969c57d7e3SVasanthakumar Thiagarajan ret = ath11k_dp_pdev_reo_setup(ab); 5979c57d7e3SVasanthakumar Thiagarajan if (ret) { 5989c57d7e3SVasanthakumar Thiagarajan ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret); 5999c57d7e3SVasanthakumar Thiagarajan goto err_mac_destroy; 6009c57d7e3SVasanthakumar Thiagarajan } 6019c57d7e3SVasanthakumar Thiagarajan 602d5c65159SKalle Valo ret = ath11k_wmi_cmd_init(ab); 603d5c65159SKalle Valo if (ret) { 604d5c65159SKalle Valo ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret); 6059c57d7e3SVasanthakumar Thiagarajan goto err_reo_cleanup; 606d5c65159SKalle Valo } 607d5c65159SKalle Valo 608d5c65159SKalle Valo ret = ath11k_wmi_wait_for_unified_ready(ab); 609d5c65159SKalle Valo if (ret) { 610d5c65159SKalle Valo ath11k_err(ab, "failed to receive wmi unified ready event: %d\n", 611d5c65159SKalle Valo ret); 6129c57d7e3SVasanthakumar Thiagarajan goto err_reo_cleanup; 613d5c65159SKalle Valo } 614d5c65159SKalle Valo 615d5c65159SKalle Valo ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab); 616d5c65159SKalle Valo if (ret) { 617d5c65159SKalle Valo ath11k_err(ab, "failed to send htt version request message: %d\n", 618d5c65159SKalle Valo ret); 6199c57d7e3SVasanthakumar Thiagarajan goto err_reo_cleanup; 620d5c65159SKalle Valo } 621d5c65159SKalle Valo 622d5c65159SKalle Valo return 0; 623d5c65159SKalle Valo 6249c57d7e3SVasanthakumar Thiagarajan err_reo_cleanup: 6259c57d7e3SVasanthakumar Thiagarajan ath11k_dp_pdev_reo_cleanup(ab); 6260366f426SVasanthakumar Thiagarajan err_mac_destroy: 6270366f426SVasanthakumar Thiagarajan ath11k_mac_destroy(ab); 628d5c65159SKalle Valo err_hif_stop: 62931858805SGovind Singh ath11k_hif_stop(ab); 630d5c65159SKalle Valo err_wmi_detach: 631d5c65159SKalle Valo ath11k_wmi_detach(ab); 632d5c65159SKalle Valo err_firmware_stop: 633d5c65159SKalle Valo ath11k_qmi_firmware_stop(ab); 634d5c65159SKalle Valo 635d5c65159SKalle Valo return ret; 636d5c65159SKalle Valo } 637d5c65159SKalle Valo 638d5c65159SKalle Valo int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) 639d5c65159SKalle Valo { 640d5c65159SKalle Valo int ret; 641d5c65159SKalle Valo 642d5c65159SKalle Valo ret = ath11k_ce_init_pipes(ab); 643d5c65159SKalle Valo if (ret) { 644d5c65159SKalle Valo ath11k_err(ab, "failed to initialize CE: %d\n", ret); 645d5c65159SKalle Valo return ret; 646d5c65159SKalle Valo } 647d5c65159SKalle Valo 648d5c65159SKalle Valo ret = ath11k_dp_alloc(ab); 649d5c65159SKalle Valo if (ret) { 650d5c65159SKalle Valo ath11k_err(ab, "failed to init DP: %d\n", ret); 651d5c65159SKalle Valo return ret; 652d5c65159SKalle Valo } 653d5c65159SKalle Valo 654aa2092a9SVenkateswara Naralasetty switch (ath11k_crypto_mode) { 655aa2092a9SVenkateswara Naralasetty case ATH11K_CRYPT_MODE_SW: 656aa2092a9SVenkateswara Naralasetty set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); 657aa2092a9SVenkateswara Naralasetty set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); 658aa2092a9SVenkateswara Naralasetty break; 659aa2092a9SVenkateswara Naralasetty case ATH11K_CRYPT_MODE_HW: 660aa2092a9SVenkateswara Naralasetty clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); 661aa2092a9SVenkateswara Naralasetty clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); 662aa2092a9SVenkateswara Naralasetty break; 663aa2092a9SVenkateswara Naralasetty default: 664aa2092a9SVenkateswara Naralasetty ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); 665aa2092a9SVenkateswara Naralasetty return -EINVAL; 666aa2092a9SVenkateswara Naralasetty } 667aa2092a9SVenkateswara Naralasetty 668aa2092a9SVenkateswara Naralasetty if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW) 669aa2092a9SVenkateswara Naralasetty set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); 670aa2092a9SVenkateswara Naralasetty 671d5c65159SKalle Valo mutex_lock(&ab->core_lock); 672d5c65159SKalle Valo ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL); 673d5c65159SKalle Valo if (ret) { 674d5c65159SKalle Valo ath11k_err(ab, "failed to start core: %d\n", ret); 675d5c65159SKalle Valo goto err_dp_free; 676d5c65159SKalle Valo } 677d5c65159SKalle Valo 678d5c65159SKalle Valo ret = ath11k_core_pdev_create(ab); 679d5c65159SKalle Valo if (ret) { 680d5c65159SKalle Valo ath11k_err(ab, "failed to create pdev core: %d\n", ret); 681d5c65159SKalle Valo goto err_core_stop; 682d5c65159SKalle Valo } 68331858805SGovind Singh ath11k_hif_irq_enable(ab); 684d5c65159SKalle Valo mutex_unlock(&ab->core_lock); 685d5c65159SKalle Valo 686d5c65159SKalle Valo return 0; 687d5c65159SKalle Valo 688d5c65159SKalle Valo err_core_stop: 689d5c65159SKalle Valo ath11k_core_stop(ab); 6900366f426SVasanthakumar Thiagarajan ath11k_mac_destroy(ab); 691d5c65159SKalle Valo err_dp_free: 692d5c65159SKalle Valo ath11k_dp_free(ab); 693ba479239SGovindaraj Saminathan mutex_unlock(&ab->core_lock); 694d5c65159SKalle Valo return ret; 695d5c65159SKalle Valo } 696d5c65159SKalle Valo 697d5c65159SKalle Valo static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab) 698d5c65159SKalle Valo { 699d5c65159SKalle Valo int ret; 700d5c65159SKalle Valo 701d5c65159SKalle Valo mutex_lock(&ab->core_lock); 7022a63bbcaSPradeep Kumar Chitrapu ath11k_thermal_unregister(ab); 70331858805SGovind Singh ath11k_hif_irq_disable(ab); 704d5c65159SKalle Valo ath11k_dp_pdev_free(ab); 7059d11b7bfSKarthikeyan Periyasamy ath11k_spectral_deinit(ab); 70631858805SGovind Singh ath11k_hif_stop(ab); 707d5c65159SKalle Valo ath11k_wmi_detach(ab); 7089c57d7e3SVasanthakumar Thiagarajan ath11k_dp_pdev_reo_cleanup(ab); 709d5c65159SKalle Valo mutex_unlock(&ab->core_lock); 710d5c65159SKalle Valo 711d5c65159SKalle Valo ath11k_dp_free(ab); 712d5c65159SKalle Valo ath11k_hal_srng_deinit(ab); 713d5c65159SKalle Valo 714d5c65159SKalle Valo ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1; 715d5c65159SKalle Valo 716d5c65159SKalle Valo ret = ath11k_hal_srng_init(ab); 717d5c65159SKalle Valo if (ret) 718d5c65159SKalle Valo return ret; 719d5c65159SKalle Valo 720d5c65159SKalle Valo clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); 721d5c65159SKalle Valo 722d5c65159SKalle Valo ret = ath11k_core_qmi_firmware_ready(ab); 723d5c65159SKalle Valo if (ret) 724d5c65159SKalle Valo goto err_hal_srng_deinit; 725d5c65159SKalle Valo 726d5c65159SKalle Valo clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); 727d5c65159SKalle Valo 728d5c65159SKalle Valo return 0; 729d5c65159SKalle Valo 730d5c65159SKalle Valo err_hal_srng_deinit: 731d5c65159SKalle Valo ath11k_hal_srng_deinit(ab); 732d5c65159SKalle Valo return ret; 733d5c65159SKalle Valo } 734d5c65159SKalle Valo 735d5c65159SKalle Valo void ath11k_core_halt(struct ath11k *ar) 736d5c65159SKalle Valo { 737d5c65159SKalle Valo struct ath11k_base *ab = ar->ab; 738d5c65159SKalle Valo 739d5c65159SKalle Valo lockdep_assert_held(&ar->conf_mutex); 740d5c65159SKalle Valo 741d5c65159SKalle Valo ar->num_created_vdevs = 0; 74279c080dbSKarthikeyan Periyasamy ar->allocated_vdev_map = 0; 743d5c65159SKalle Valo 744d5c65159SKalle Valo ath11k_mac_scan_finish(ar); 745d5c65159SKalle Valo ath11k_mac_peer_cleanup_all(ar); 746d5c65159SKalle Valo cancel_delayed_work_sync(&ar->scan.timeout); 747d5c65159SKalle Valo cancel_work_sync(&ar->regd_update_work); 748d5c65159SKalle Valo 749d5c65159SKalle Valo rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL); 750d5c65159SKalle Valo synchronize_rcu(); 751d5c65159SKalle Valo INIT_LIST_HEAD(&ar->arvifs); 752d5c65159SKalle Valo idr_init(&ar->txmgmt_idr); 753d5c65159SKalle Valo } 754d5c65159SKalle Valo 755d5c65159SKalle Valo static void ath11k_core_restart(struct work_struct *work) 756d5c65159SKalle Valo { 757d5c65159SKalle Valo struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); 758d5c65159SKalle Valo struct ath11k *ar; 759d5c65159SKalle Valo struct ath11k_pdev *pdev; 760d5c65159SKalle Valo int i, ret = 0; 761d5c65159SKalle Valo 762d5c65159SKalle Valo spin_lock_bh(&ab->base_lock); 763d5c65159SKalle Valo ab->stats.fw_crash_counter++; 764d5c65159SKalle Valo spin_unlock_bh(&ab->base_lock); 765d5c65159SKalle Valo 766d5c65159SKalle Valo for (i = 0; i < ab->num_radios; i++) { 767d5c65159SKalle Valo pdev = &ab->pdevs[i]; 768d5c65159SKalle Valo ar = pdev->ar; 769d5c65159SKalle Valo if (!ar || ar->state == ATH11K_STATE_OFF) 770d5c65159SKalle Valo continue; 771d5c65159SKalle Valo 772d5c65159SKalle Valo ieee80211_stop_queues(ar->hw); 773d5c65159SKalle Valo ath11k_mac_drain_tx(ar); 774d5c65159SKalle Valo complete(&ar->scan.started); 775d5c65159SKalle Valo complete(&ar->scan.completed); 776d5c65159SKalle Valo complete(&ar->peer_assoc_done); 777d5c65159SKalle Valo complete(&ar->install_key_done); 778d5c65159SKalle Valo complete(&ar->vdev_setup_done); 779d5c65159SKalle Valo complete(&ar->bss_survey_done); 780a41d1034SPradeep Kumar Chitrapu complete(&ar->thermal.wmi_sync); 781d5c65159SKalle Valo 782d5c65159SKalle Valo wake_up(&ar->dp.tx_empty_waitq); 783d5c65159SKalle Valo idr_for_each(&ar->txmgmt_idr, 784d5c65159SKalle Valo ath11k_mac_tx_mgmt_pending_free, ar); 785d5c65159SKalle Valo idr_destroy(&ar->txmgmt_idr); 786d5c65159SKalle Valo } 787d5c65159SKalle Valo 7886bc9d6f7SJohn Crispin wake_up(&ab->wmi_ab.tx_credits_wq); 789d5c65159SKalle Valo wake_up(&ab->peer_mapping_wq); 790d5c65159SKalle Valo 791d5c65159SKalle Valo ret = ath11k_core_reconfigure_on_crash(ab); 792d5c65159SKalle Valo if (ret) { 793d5c65159SKalle Valo ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); 794d5c65159SKalle Valo return; 795d5c65159SKalle Valo } 796d5c65159SKalle Valo 797d5c65159SKalle Valo for (i = 0; i < ab->num_radios; i++) { 798d5c65159SKalle Valo pdev = &ab->pdevs[i]; 799d5c65159SKalle Valo ar = pdev->ar; 800d5c65159SKalle Valo if (!ar || ar->state == ATH11K_STATE_OFF) 801d5c65159SKalle Valo continue; 802d5c65159SKalle Valo 803d5c65159SKalle Valo mutex_lock(&ar->conf_mutex); 804d5c65159SKalle Valo 805d5c65159SKalle Valo switch (ar->state) { 806d5c65159SKalle Valo case ATH11K_STATE_ON: 807d5c65159SKalle Valo ar->state = ATH11K_STATE_RESTARTING; 808d5c65159SKalle Valo ath11k_core_halt(ar); 809d5c65159SKalle Valo ieee80211_restart_hw(ar->hw); 810d5c65159SKalle Valo break; 811d5c65159SKalle Valo case ATH11K_STATE_OFF: 812d5c65159SKalle Valo ath11k_warn(ab, 813d5c65159SKalle Valo "cannot restart radio %d that hasn't been started\n", 814d5c65159SKalle Valo i); 815d5c65159SKalle Valo break; 816d5c65159SKalle Valo case ATH11K_STATE_RESTARTING: 817d5c65159SKalle Valo break; 818d5c65159SKalle Valo case ATH11K_STATE_RESTARTED: 819d5c65159SKalle Valo ar->state = ATH11K_STATE_WEDGED; 8200b294aebSGustavo A. R. Silva fallthrough; 821d5c65159SKalle Valo case ATH11K_STATE_WEDGED: 822d5c65159SKalle Valo ath11k_warn(ab, 823d5c65159SKalle Valo "device is wedged, will not restart radio %d\n", i); 824d5c65159SKalle Valo break; 825d5c65159SKalle Valo } 826d5c65159SKalle Valo mutex_unlock(&ar->conf_mutex); 827d5c65159SKalle Valo } 828d5c65159SKalle Valo complete(&ab->driver_recovery); 829d5c65159SKalle Valo } 830d5c65159SKalle Valo 831d3318abfSAnilkumar Kolli static int ath11k_init_hw_params(struct ath11k_base *ab) 832d3318abfSAnilkumar Kolli { 833d3318abfSAnilkumar Kolli const struct ath11k_hw_params *hw_params = NULL; 834d3318abfSAnilkumar Kolli int i; 835d3318abfSAnilkumar Kolli 836d3318abfSAnilkumar Kolli for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) { 837d3318abfSAnilkumar Kolli hw_params = &ath11k_hw_params[i]; 838d3318abfSAnilkumar Kolli 839d3318abfSAnilkumar Kolli if (hw_params->hw_rev == ab->hw_rev) 840d3318abfSAnilkumar Kolli break; 841d3318abfSAnilkumar Kolli } 842d3318abfSAnilkumar Kolli 843d3318abfSAnilkumar Kolli if (i == ARRAY_SIZE(ath11k_hw_params)) { 844d3318abfSAnilkumar Kolli ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev); 845d3318abfSAnilkumar Kolli return -EINVAL; 846d3318abfSAnilkumar Kolli } 847d3318abfSAnilkumar Kolli 848d3318abfSAnilkumar Kolli ab->hw_params = *hw_params; 849d3318abfSAnilkumar Kolli 850d3318abfSAnilkumar Kolli ath11k_dbg(ab, ATH11K_DBG_BOOT, "Hardware name %s\n", ab->hw_params.name); 851d3318abfSAnilkumar Kolli 852d3318abfSAnilkumar Kolli return 0; 853d3318abfSAnilkumar Kolli } 854d3318abfSAnilkumar Kolli 855b8246f88SKalle Valo int ath11k_core_pre_init(struct ath11k_base *ab) 856b8246f88SKalle Valo { 857b8246f88SKalle Valo int ret; 858b8246f88SKalle Valo 859b8246f88SKalle Valo ret = ath11k_init_hw_params(ab); 860b8246f88SKalle Valo if (ret) { 861b8246f88SKalle Valo ath11k_err(ab, "failed to get hw params: %d\n", ret); 862b8246f88SKalle Valo return ret; 863b8246f88SKalle Valo } 864b8246f88SKalle Valo 865b8246f88SKalle Valo return 0; 866b8246f88SKalle Valo } 867b8246f88SKalle Valo EXPORT_SYMBOL(ath11k_core_pre_init); 868b8246f88SKalle Valo 8691ff8ed78SGovind Singh int ath11k_core_init(struct ath11k_base *ab) 8701ff8ed78SGovind Singh { 8711ff8ed78SGovind Singh int ret; 8721ff8ed78SGovind Singh 873d5c65159SKalle Valo ret = ath11k_core_soc_create(ab); 874d5c65159SKalle Valo if (ret) { 875d5c65159SKalle Valo ath11k_err(ab, "failed to create soc core: %d\n", ret); 876d5c65159SKalle Valo return ret; 877d5c65159SKalle Valo } 878d5c65159SKalle Valo 879d5c65159SKalle Valo return 0; 880d5c65159SKalle Valo } 8817f4beda2SGovind Singh EXPORT_SYMBOL(ath11k_core_init); 882d5c65159SKalle Valo 883d5c65159SKalle Valo void ath11k_core_deinit(struct ath11k_base *ab) 884d5c65159SKalle Valo { 885d5c65159SKalle Valo mutex_lock(&ab->core_lock); 886d5c65159SKalle Valo 887d5c65159SKalle Valo ath11k_core_pdev_destroy(ab); 888d5c65159SKalle Valo ath11k_core_stop(ab); 889d5c65159SKalle Valo 890d5c65159SKalle Valo mutex_unlock(&ab->core_lock); 891d5c65159SKalle Valo 89231858805SGovind Singh ath11k_hif_power_down(ab); 893d5c65159SKalle Valo ath11k_mac_destroy(ab); 894d5c65159SKalle Valo ath11k_core_soc_destroy(ab); 895d5c65159SKalle Valo } 8966e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_deinit); 897d5c65159SKalle Valo 898d5c65159SKalle Valo void ath11k_core_free(struct ath11k_base *ab) 899d5c65159SKalle Valo { 900d5c65159SKalle Valo kfree(ab); 901d5c65159SKalle Valo } 9026e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_free); 903d5c65159SKalle Valo 904630ad41cSGovind Singh struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, 9051ff8ed78SGovind Singh enum ath11k_bus bus, 9061ff8ed78SGovind Singh const struct ath11k_bus_params *bus_params) 907d5c65159SKalle Valo { 908d5c65159SKalle Valo struct ath11k_base *ab; 909d5c65159SKalle Valo 910630ad41cSGovind Singh ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL); 911d5c65159SKalle Valo if (!ab) 912d5c65159SKalle Valo return NULL; 913d5c65159SKalle Valo 914d5c65159SKalle Valo init_completion(&ab->driver_recovery); 915d5c65159SKalle Valo 916d5c65159SKalle Valo ab->workqueue = create_singlethread_workqueue("ath11k_wq"); 917d5c65159SKalle Valo if (!ab->workqueue) 918d5c65159SKalle Valo goto err_sc_free; 919d5c65159SKalle Valo 920d5c65159SKalle Valo mutex_init(&ab->core_lock); 921d5c65159SKalle Valo spin_lock_init(&ab->base_lock); 922d5c65159SKalle Valo 923d5c65159SKalle Valo INIT_LIST_HEAD(&ab->peers); 924d5c65159SKalle Valo init_waitqueue_head(&ab->peer_mapping_wq); 9256bc9d6f7SJohn Crispin init_waitqueue_head(&ab->wmi_ab.tx_credits_wq); 926d5c65159SKalle Valo INIT_WORK(&ab->restart_work, ath11k_core_restart); 927d5c65159SKalle Valo timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); 928d5c65159SKalle Valo ab->dev = dev; 9291ff8ed78SGovind Singh ab->bus_params = *bus_params; 9306eb6ea51SGovind Singh ab->hif.bus = bus; 931d5c65159SKalle Valo 932d5c65159SKalle Valo return ab; 933d5c65159SKalle Valo 934d5c65159SKalle Valo err_sc_free: 935d5c65159SKalle Valo kfree(ab); 936d5c65159SKalle Valo return NULL; 937d5c65159SKalle Valo } 9386e0355afSGovind Singh EXPORT_SYMBOL(ath11k_core_alloc); 9396e0355afSGovind Singh 9406e0355afSGovind Singh MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards."); 9416e0355afSGovind Singh MODULE_LICENSE("Dual BSD/GPL"); 942