3744 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2005-2011 Atheros Communications Inc.4 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.5 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.6 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.7 */8 9#include <linux/module.h>10#include <linux/firmware.h>11#include <linux/of.h>12#include <linux/property.h>13#include <linux/dmi.h>14#include <linux/ctype.h>15#include <linux/pm_qos.h>16#include <linux/nvmem-consumer.h>17#include <asm/byteorder.h>18 19#include "core.h"20#include "mac.h"21#include "htc.h"22#include "hif.h"23#include "wmi.h"24#include "bmi.h"25#include "debug.h"26#include "htt.h"27#include "testmode.h"28#include "wmi-ops.h"29#include "coredump.h"30#include "leds.h"31 32unsigned int ath10k_debug_mask;33EXPORT_SYMBOL(ath10k_debug_mask);34 35static unsigned int ath10k_cryptmode_param;36static bool uart_print;37static bool skip_otp;38static bool fw_diag_log;39 40/* frame mode values are mapped as per enum ath10k_hw_txrx_mode */41unsigned int ath10k_frame_mode = ATH10K_HW_TXRX_NATIVE_WIFI;42 43unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |44 BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);45 46/* FIXME: most of these should be readonly */47module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);48module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);49module_param(uart_print, bool, 0644);50module_param(skip_otp, bool, 0644);51module_param(fw_diag_log, bool, 0644);52module_param_named(frame_mode, ath10k_frame_mode, uint, 0644);53module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);54 55MODULE_PARM_DESC(debug_mask, "Debugging mask");56MODULE_PARM_DESC(uart_print, "Uart target debugging");57MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");58MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");59MODULE_PARM_DESC(frame_mode,60 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");61MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");62MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");63 64static const struct ath10k_hw_params ath10k_hw_params_list[] = {65 {66 .id = QCA988X_HW_2_0_VERSION,67 .dev_id = QCA988X_2_0_DEVICE_ID,68 .bus = ATH10K_BUS_PCI,69 .name = "qca988x hw2.0",70 .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,71 .uart_pin = 7,72 .led_pin = 1,73 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,74 .otp_exe_param = 0,75 .channel_counters_freq_hz = 88000,76 .max_probe_resp_desc_thres = 0,77 .cal_data_len = 2116,78 .fw = {79 .dir = QCA988X_HW_2_0_FW_DIR,80 .board_size = QCA988X_BOARD_DATA_SZ,81 .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,82 },83 .rx_desc_ops = &qca988x_rx_desc_ops,84 .hw_ops = &qca988x_ops,85 .decap_align_bytes = 4,86 .spectral_bin_discard = 0,87 .spectral_bin_offset = 0,88 .vht160_mcs_rx_highest = 0,89 .vht160_mcs_tx_highest = 0,90 .n_cipher_suites = 8,91 .ast_skid_limit = 0x10,92 .num_wds_entries = 0x20,93 .target_64bit = false,94 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,95 .shadow_reg_support = false,96 .rri_on_ddr = false,97 .hw_filter_reset_required = true,98 .fw_diag_ce_download = false,99 .credit_size_workaround = false,100 .tx_stats_over_pktlog = true,101 .dynamic_sar_support = false,102 .hw_restart_disconnect = false,103 .use_fw_tx_credits = true,104 .delay_unmap_buffer = false,105 .mcast_frame_registration = false,106 },107 {108 .id = QCA988X_HW_2_0_VERSION,109 .dev_id = QCA988X_2_0_DEVICE_ID_UBNT,110 .name = "qca988x hw2.0 ubiquiti",111 .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,112 .uart_pin = 7,113 .led_pin = 0,114 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,115 .otp_exe_param = 0,116 .channel_counters_freq_hz = 88000,117 .max_probe_resp_desc_thres = 0,118 .cal_data_len = 2116,119 .fw = {120 .dir = QCA988X_HW_2_0_FW_DIR,121 .board_size = QCA988X_BOARD_DATA_SZ,122 .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,123 },124 .rx_desc_ops = &qca988x_rx_desc_ops,125 .hw_ops = &qca988x_ops,126 .decap_align_bytes = 4,127 .spectral_bin_discard = 0,128 .spectral_bin_offset = 0,129 .vht160_mcs_rx_highest = 0,130 .vht160_mcs_tx_highest = 0,131 .n_cipher_suites = 8,132 .ast_skid_limit = 0x10,133 .num_wds_entries = 0x20,134 .target_64bit = false,135 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,136 .shadow_reg_support = false,137 .rri_on_ddr = false,138 .hw_filter_reset_required = true,139 .fw_diag_ce_download = false,140 .credit_size_workaround = false,141 .tx_stats_over_pktlog = true,142 .dynamic_sar_support = false,143 .hw_restart_disconnect = false,144 .use_fw_tx_credits = true,145 .delay_unmap_buffer = false,146 .mcast_frame_registration = false,147 },148 {149 .id = QCA9887_HW_1_0_VERSION,150 .dev_id = QCA9887_1_0_DEVICE_ID,151 .bus = ATH10K_BUS_PCI,152 .name = "qca9887 hw1.0",153 .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,154 .uart_pin = 7,155 .led_pin = 1,156 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,157 .otp_exe_param = 0,158 .channel_counters_freq_hz = 88000,159 .max_probe_resp_desc_thres = 0,160 .cal_data_len = 2116,161 .fw = {162 .dir = QCA9887_HW_1_0_FW_DIR,163 .board_size = QCA9887_BOARD_DATA_SZ,164 .board_ext_size = QCA9887_BOARD_EXT_DATA_SZ,165 },166 .rx_desc_ops = &qca988x_rx_desc_ops,167 .hw_ops = &qca988x_ops,168 .decap_align_bytes = 4,169 .spectral_bin_discard = 0,170 .spectral_bin_offset = 0,171 .vht160_mcs_rx_highest = 0,172 .vht160_mcs_tx_highest = 0,173 .n_cipher_suites = 8,174 .ast_skid_limit = 0x10,175 .num_wds_entries = 0x20,176 .target_64bit = false,177 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,178 .shadow_reg_support = false,179 .rri_on_ddr = false,180 .hw_filter_reset_required = true,181 .fw_diag_ce_download = false,182 .credit_size_workaround = false,183 .tx_stats_over_pktlog = false,184 .dynamic_sar_support = false,185 .hw_restart_disconnect = false,186 .use_fw_tx_credits = true,187 .delay_unmap_buffer = false,188 .mcast_frame_registration = false,189 },190 {191 .id = QCA6174_HW_3_2_VERSION,192 .dev_id = QCA6174_3_2_DEVICE_ID,193 .bus = ATH10K_BUS_SDIO,194 .name = "qca6174 hw3.2 sdio",195 .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,196 .uart_pin = 19,197 .led_pin = 0,198 .otp_exe_param = 0,199 .channel_counters_freq_hz = 88000,200 .max_probe_resp_desc_thres = 0,201 .cal_data_len = 0,202 .fw = {203 .dir = QCA6174_HW_3_0_FW_DIR,204 .board_size = QCA6174_BOARD_DATA_SZ,205 .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,206 },207 .rx_desc_ops = &qca988x_rx_desc_ops,208 .hw_ops = &qca6174_sdio_ops,209 .hw_clk = qca6174_clk,210 .target_cpu_freq = 176000000,211 .decap_align_bytes = 4,212 .n_cipher_suites = 8,213 .num_peers = 10,214 .ast_skid_limit = 0x10,215 .num_wds_entries = 0x20,216 .uart_pin_workaround = true,217 .tx_stats_over_pktlog = false,218 .credit_size_workaround = false,219 .bmi_large_size_download = true,220 .supports_peer_stats_info = true,221 .dynamic_sar_support = true,222 .hw_restart_disconnect = false,223 .use_fw_tx_credits = true,224 .delay_unmap_buffer = false,225 .mcast_frame_registration = false,226 },227 {228 .id = QCA6174_HW_2_1_VERSION,229 .dev_id = QCA6164_2_1_DEVICE_ID,230 .bus = ATH10K_BUS_PCI,231 .name = "qca6164 hw2.1",232 .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,233 .uart_pin = 6,234 .led_pin = 0,235 .otp_exe_param = 0,236 .channel_counters_freq_hz = 88000,237 .max_probe_resp_desc_thres = 0,238 .cal_data_len = 8124,239 .fw = {240 .dir = QCA6174_HW_2_1_FW_DIR,241 .board_size = QCA6174_BOARD_DATA_SZ,242 .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,243 },244 .rx_desc_ops = &qca988x_rx_desc_ops,245 .hw_ops = &qca988x_ops,246 .decap_align_bytes = 4,247 .spectral_bin_discard = 0,248 .spectral_bin_offset = 0,249 .vht160_mcs_rx_highest = 0,250 .vht160_mcs_tx_highest = 0,251 .n_cipher_suites = 8,252 .ast_skid_limit = 0x10,253 .num_wds_entries = 0x20,254 .target_64bit = false,255 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,256 .shadow_reg_support = false,257 .rri_on_ddr = false,258 .hw_filter_reset_required = true,259 .fw_diag_ce_download = false,260 .credit_size_workaround = false,261 .tx_stats_over_pktlog = false,262 .dynamic_sar_support = false,263 .hw_restart_disconnect = false,264 .use_fw_tx_credits = true,265 .delay_unmap_buffer = false,266 .mcast_frame_registration = false,267 },268 {269 .id = QCA6174_HW_2_1_VERSION,270 .dev_id = QCA6174_2_1_DEVICE_ID,271 .bus = ATH10K_BUS_PCI,272 .name = "qca6174 hw2.1",273 .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,274 .uart_pin = 6,275 .led_pin = 0,276 .otp_exe_param = 0,277 .channel_counters_freq_hz = 88000,278 .max_probe_resp_desc_thres = 0,279 .cal_data_len = 8124,280 .fw = {281 .dir = QCA6174_HW_2_1_FW_DIR,282 .board_size = QCA6174_BOARD_DATA_SZ,283 .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,284 },285 .rx_desc_ops = &qca988x_rx_desc_ops,286 .hw_ops = &qca988x_ops,287 .decap_align_bytes = 4,288 .spectral_bin_discard = 0,289 .spectral_bin_offset = 0,290 .vht160_mcs_rx_highest = 0,291 .vht160_mcs_tx_highest = 0,292 .n_cipher_suites = 8,293 .ast_skid_limit = 0x10,294 .num_wds_entries = 0x20,295 .target_64bit = false,296 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,297 .shadow_reg_support = false,298 .rri_on_ddr = false,299 .hw_filter_reset_required = true,300 .fw_diag_ce_download = false,301 .credit_size_workaround = false,302 .tx_stats_over_pktlog = false,303 .dynamic_sar_support = false,304 .hw_restart_disconnect = false,305 .use_fw_tx_credits = true,306 .delay_unmap_buffer = false,307 .mcast_frame_registration = false,308 },309 {310 .id = QCA6174_HW_3_0_VERSION,311 .dev_id = QCA6174_2_1_DEVICE_ID,312 .bus = ATH10K_BUS_PCI,313 .name = "qca6174 hw3.0",314 .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,315 .uart_pin = 6,316 .led_pin = 0,317 .otp_exe_param = 0,318 .channel_counters_freq_hz = 88000,319 .max_probe_resp_desc_thres = 0,320 .cal_data_len = 8124,321 .fw = {322 .dir = QCA6174_HW_3_0_FW_DIR,323 .board_size = QCA6174_BOARD_DATA_SZ,324 .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,325 },326 .rx_desc_ops = &qca988x_rx_desc_ops,327 .hw_ops = &qca988x_ops,328 .decap_align_bytes = 4,329 .spectral_bin_discard = 0,330 .spectral_bin_offset = 0,331 .vht160_mcs_rx_highest = 0,332 .vht160_mcs_tx_highest = 0,333 .n_cipher_suites = 8,334 .ast_skid_limit = 0x10,335 .num_wds_entries = 0x20,336 .target_64bit = false,337 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,338 .shadow_reg_support = false,339 .rri_on_ddr = false,340 .hw_filter_reset_required = true,341 .fw_diag_ce_download = false,342 .credit_size_workaround = false,343 .tx_stats_over_pktlog = false,344 .dynamic_sar_support = false,345 .hw_restart_disconnect = false,346 .use_fw_tx_credits = true,347 .delay_unmap_buffer = false,348 .mcast_frame_registration = false,349 },350 {351 .id = QCA6174_HW_3_2_VERSION,352 .dev_id = QCA6174_2_1_DEVICE_ID,353 .bus = ATH10K_BUS_PCI,354 .name = "qca6174 hw3.2",355 .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,356 .uart_pin = 6,357 .led_pin = 0,358 .otp_exe_param = 0,359 .channel_counters_freq_hz = 88000,360 .max_probe_resp_desc_thres = 0,361 .cal_data_len = 8124,362 .fw = {363 /* uses same binaries as hw3.0 */364 .dir = QCA6174_HW_3_0_FW_DIR,365 .board_size = QCA6174_BOARD_DATA_SZ,366 .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,367 },368 .rx_desc_ops = &qca988x_rx_desc_ops,369 .hw_ops = &qca6174_ops,370 .hw_clk = qca6174_clk,371 .target_cpu_freq = 176000000,372 .decap_align_bytes = 4,373 .spectral_bin_discard = 0,374 .spectral_bin_offset = 0,375 .vht160_mcs_rx_highest = 0,376 .vht160_mcs_tx_highest = 0,377 .n_cipher_suites = 8,378 .ast_skid_limit = 0x10,379 .num_wds_entries = 0x20,380 .target_64bit = false,381 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,382 .shadow_reg_support = false,383 .rri_on_ddr = false,384 .hw_filter_reset_required = true,385 .fw_diag_ce_download = true,386 .credit_size_workaround = false,387 .tx_stats_over_pktlog = false,388 .supports_peer_stats_info = true,389 .dynamic_sar_support = true,390 .hw_restart_disconnect = false,391 .use_fw_tx_credits = true,392 .delay_unmap_buffer = false,393 .mcast_frame_registration = true,394 },395 {396 .id = QCA99X0_HW_2_0_DEV_VERSION,397 .dev_id = QCA99X0_2_0_DEVICE_ID,398 .bus = ATH10K_BUS_PCI,399 .name = "qca99x0 hw2.0",400 .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,401 .uart_pin = 7,402 .led_pin = 17,403 .otp_exe_param = 0x00000700,404 .continuous_frag_desc = true,405 .cck_rate_map_rev2 = true,406 .channel_counters_freq_hz = 150000,407 .max_probe_resp_desc_thres = 24,408 .tx_chain_mask = 0xf,409 .rx_chain_mask = 0xf,410 .max_spatial_stream = 4,411 .cal_data_len = 12064,412 .fw = {413 .dir = QCA99X0_HW_2_0_FW_DIR,414 .board_size = QCA99X0_BOARD_DATA_SZ,415 .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,416 },417 .sw_decrypt_mcast_mgmt = true,418 .rx_desc_ops = &qca99x0_rx_desc_ops,419 .hw_ops = &qca99x0_ops,420 .decap_align_bytes = 1,421 .spectral_bin_discard = 4,422 .spectral_bin_offset = 0,423 .vht160_mcs_rx_highest = 0,424 .vht160_mcs_tx_highest = 0,425 .n_cipher_suites = 11,426 .ast_skid_limit = 0x10,427 .num_wds_entries = 0x20,428 .target_64bit = false,429 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,430 .shadow_reg_support = false,431 .rri_on_ddr = false,432 .hw_filter_reset_required = true,433 .fw_diag_ce_download = false,434 .credit_size_workaround = false,435 .tx_stats_over_pktlog = false,436 .dynamic_sar_support = false,437 .hw_restart_disconnect = false,438 .use_fw_tx_credits = true,439 .delay_unmap_buffer = false,440 .mcast_frame_registration = false,441 },442 {443 .id = QCA9984_HW_1_0_DEV_VERSION,444 .dev_id = QCA9984_1_0_DEVICE_ID,445 .bus = ATH10K_BUS_PCI,446 .name = "qca9984/qca9994 hw1.0",447 .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,448 .uart_pin = 7,449 .led_pin = 17,450 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,451 .otp_exe_param = 0x00000700,452 .continuous_frag_desc = true,453 .cck_rate_map_rev2 = true,454 .channel_counters_freq_hz = 150000,455 .max_probe_resp_desc_thres = 24,456 .tx_chain_mask = 0xf,457 .rx_chain_mask = 0xf,458 .max_spatial_stream = 4,459 .cal_data_len = 12064,460 .fw = {461 .dir = QCA9984_HW_1_0_FW_DIR,462 .board_size = QCA99X0_BOARD_DATA_SZ,463 .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,464 .ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ,465 },466 .sw_decrypt_mcast_mgmt = true,467 .rx_desc_ops = &qca99x0_rx_desc_ops,468 .hw_ops = &qca99x0_ops,469 .decap_align_bytes = 1,470 .spectral_bin_discard = 12,471 .spectral_bin_offset = 8,472 473 /* Can do only 2x2 VHT160 or 80+80. 1560Mbps is 4x4 80Mhz474 * or 2x2 160Mhz, long-guard-interval.475 */476 .vht160_mcs_rx_highest = 1560,477 .vht160_mcs_tx_highest = 1560,478 .n_cipher_suites = 11,479 .ast_skid_limit = 0x10,480 .num_wds_entries = 0x20,481 .target_64bit = false,482 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,483 .shadow_reg_support = false,484 .rri_on_ddr = false,485 .hw_filter_reset_required = true,486 .fw_diag_ce_download = false,487 .credit_size_workaround = false,488 .tx_stats_over_pktlog = false,489 .dynamic_sar_support = false,490 .hw_restart_disconnect = false,491 .use_fw_tx_credits = true,492 .delay_unmap_buffer = false,493 .mcast_frame_registration = false,494 },495 {496 .id = QCA9888_HW_2_0_DEV_VERSION,497 .dev_id = QCA9888_2_0_DEVICE_ID,498 .bus = ATH10K_BUS_PCI,499 .name = "qca9888 hw2.0",500 .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,501 .uart_pin = 7,502 .led_pin = 17,503 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,504 .otp_exe_param = 0x00000700,505 .continuous_frag_desc = true,506 .channel_counters_freq_hz = 150000,507 .max_probe_resp_desc_thres = 24,508 .tx_chain_mask = 3,509 .rx_chain_mask = 3,510 .max_spatial_stream = 2,511 .cal_data_len = 12064,512 .fw = {513 .dir = QCA9888_HW_2_0_FW_DIR,514 .board_size = QCA99X0_BOARD_DATA_SZ,515 .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,516 },517 .sw_decrypt_mcast_mgmt = true,518 .rx_desc_ops = &qca99x0_rx_desc_ops,519 .hw_ops = &qca99x0_ops,520 .decap_align_bytes = 1,521 .spectral_bin_discard = 12,522 .spectral_bin_offset = 8,523 524 /* Can do only 1x1 VHT160 or 80+80. 780Mbps is 2x2 80Mhz or525 * 1x1 160Mhz, long-guard-interval.526 */527 .vht160_mcs_rx_highest = 780,528 .vht160_mcs_tx_highest = 780,529 .n_cipher_suites = 11,530 .ast_skid_limit = 0x10,531 .num_wds_entries = 0x20,532 .target_64bit = false,533 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,534 .shadow_reg_support = false,535 .rri_on_ddr = false,536 .hw_filter_reset_required = true,537 .fw_diag_ce_download = false,538 .credit_size_workaround = false,539 .tx_stats_over_pktlog = false,540 .dynamic_sar_support = false,541 .hw_restart_disconnect = false,542 .use_fw_tx_credits = true,543 .delay_unmap_buffer = false,544 .mcast_frame_registration = false,545 },546 {547 .id = QCA9377_HW_1_0_DEV_VERSION,548 .dev_id = QCA9377_1_0_DEVICE_ID,549 .bus = ATH10K_BUS_PCI,550 .name = "qca9377 hw1.0",551 .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,552 .uart_pin = 6,553 .led_pin = 0,554 .otp_exe_param = 0,555 .channel_counters_freq_hz = 88000,556 .max_probe_resp_desc_thres = 0,557 .cal_data_len = 8124,558 .fw = {559 .dir = QCA9377_HW_1_0_FW_DIR,560 .board_size = QCA9377_BOARD_DATA_SZ,561 .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,562 },563 .rx_desc_ops = &qca988x_rx_desc_ops,564 .hw_ops = &qca988x_ops,565 .decap_align_bytes = 4,566 .spectral_bin_discard = 0,567 .spectral_bin_offset = 0,568 .vht160_mcs_rx_highest = 0,569 .vht160_mcs_tx_highest = 0,570 .n_cipher_suites = 8,571 .ast_skid_limit = 0x10,572 .num_wds_entries = 0x20,573 .target_64bit = false,574 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,575 .shadow_reg_support = false,576 .rri_on_ddr = false,577 .hw_filter_reset_required = true,578 .fw_diag_ce_download = false,579 .credit_size_workaround = false,580 .tx_stats_over_pktlog = false,581 .dynamic_sar_support = false,582 .hw_restart_disconnect = false,583 .use_fw_tx_credits = true,584 .delay_unmap_buffer = false,585 .mcast_frame_registration = false,586 },587 {588 .id = QCA9377_HW_1_1_DEV_VERSION,589 .dev_id = QCA9377_1_0_DEVICE_ID,590 .bus = ATH10K_BUS_PCI,591 .name = "qca9377 hw1.1",592 .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,593 .uart_pin = 6,594 .led_pin = 0,595 .otp_exe_param = 0,596 .channel_counters_freq_hz = 88000,597 .max_probe_resp_desc_thres = 0,598 .cal_data_len = 8124,599 .fw = {600 .dir = QCA9377_HW_1_0_FW_DIR,601 .board_size = QCA9377_BOARD_DATA_SZ,602 .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,603 },604 .rx_desc_ops = &qca988x_rx_desc_ops,605 .hw_ops = &qca6174_ops,606 .hw_clk = qca6174_clk,607 .target_cpu_freq = 176000000,608 .decap_align_bytes = 4,609 .spectral_bin_discard = 0,610 .spectral_bin_offset = 0,611 .vht160_mcs_rx_highest = 0,612 .vht160_mcs_tx_highest = 0,613 .n_cipher_suites = 8,614 .ast_skid_limit = 0x10,615 .num_wds_entries = 0x20,616 .target_64bit = false,617 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,618 .shadow_reg_support = false,619 .rri_on_ddr = false,620 .hw_filter_reset_required = true,621 .fw_diag_ce_download = true,622 .credit_size_workaround = false,623 .tx_stats_over_pktlog = false,624 .dynamic_sar_support = false,625 .hw_restart_disconnect = false,626 .use_fw_tx_credits = true,627 .delay_unmap_buffer = false,628 .mcast_frame_registration = false,629 },630 {631 .id = QCA9377_HW_1_1_DEV_VERSION,632 .dev_id = QCA9377_1_0_DEVICE_ID,633 .bus = ATH10K_BUS_SDIO,634 .name = "qca9377 hw1.1 sdio",635 .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,636 .uart_pin = 19,637 .led_pin = 0,638 .otp_exe_param = 0,639 .channel_counters_freq_hz = 88000,640 .max_probe_resp_desc_thres = 0,641 .cal_data_len = 8124,642 .fw = {643 .dir = QCA9377_HW_1_0_FW_DIR,644 .board_size = QCA9377_BOARD_DATA_SZ,645 .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,646 },647 .rx_desc_ops = &qca988x_rx_desc_ops,648 .hw_ops = &qca6174_ops,649 .hw_clk = qca6174_clk,650 .target_cpu_freq = 176000000,651 .decap_align_bytes = 4,652 .n_cipher_suites = 8,653 .num_peers = TARGET_QCA9377_HL_NUM_PEERS,654 .ast_skid_limit = 0x10,655 .num_wds_entries = 0x20,656 .uart_pin_workaround = true,657 .credit_size_workaround = true,658 .dynamic_sar_support = false,659 .hw_restart_disconnect = false,660 .use_fw_tx_credits = true,661 .delay_unmap_buffer = false,662 .mcast_frame_registration = false,663 },664 {665 .id = QCA4019_HW_1_0_DEV_VERSION,666 .dev_id = 0,667 .bus = ATH10K_BUS_AHB,668 .name = "qca4019 hw1.0",669 .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,670 .uart_pin = 7,671 .led_pin = 0,672 .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,673 .otp_exe_param = 0x0010000,674 .continuous_frag_desc = true,675 .cck_rate_map_rev2 = true,676 .channel_counters_freq_hz = 125000,677 .max_probe_resp_desc_thres = 24,678 .tx_chain_mask = 0x3,679 .rx_chain_mask = 0x3,680 .max_spatial_stream = 2,681 .cal_data_len = 12064,682 .fw = {683 .dir = QCA4019_HW_1_0_FW_DIR,684 .board_size = QCA4019_BOARD_DATA_SZ,685 .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,686 },687 .sw_decrypt_mcast_mgmt = true,688 .rx_desc_ops = &qca99x0_rx_desc_ops,689 .hw_ops = &qca99x0_ops,690 .decap_align_bytes = 1,691 .spectral_bin_discard = 4,692 .spectral_bin_offset = 0,693 .vht160_mcs_rx_highest = 0,694 .vht160_mcs_tx_highest = 0,695 .n_cipher_suites = 11,696 .ast_skid_limit = 0x10,697 .num_wds_entries = 0x20,698 .target_64bit = false,699 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,700 .shadow_reg_support = false,701 .rri_on_ddr = false,702 .hw_filter_reset_required = true,703 .fw_diag_ce_download = false,704 .credit_size_workaround = false,705 .tx_stats_over_pktlog = false,706 .dynamic_sar_support = false,707 .hw_restart_disconnect = false,708 .use_fw_tx_credits = true,709 .delay_unmap_buffer = false,710 .mcast_frame_registration = false,711 },712 {713 .id = WCN3990_HW_1_0_DEV_VERSION,714 .dev_id = 0,715 .bus = ATH10K_BUS_SNOC,716 .name = "wcn3990 hw1.0",717 .led_pin = 0,718 .continuous_frag_desc = true,719 .tx_chain_mask = 0x7,720 .rx_chain_mask = 0x7,721 .max_spatial_stream = 4,722 .fw = {723 .dir = WCN3990_HW_1_0_FW_DIR,724 .board_size = WCN3990_BOARD_DATA_SZ,725 .board_ext_size = WCN3990_BOARD_EXT_DATA_SZ,726 },727 .sw_decrypt_mcast_mgmt = true,728 .rx_desc_ops = &wcn3990_rx_desc_ops,729 .hw_ops = &wcn3990_ops,730 .decap_align_bytes = 1,731 .num_peers = TARGET_HL_TLV_NUM_PEERS,732 .n_cipher_suites = 11,733 .ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT,734 .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,735 .target_64bit = true,736 .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,737 .shadow_reg_support = true,738 .rri_on_ddr = true,739 .hw_filter_reset_required = false,740 .fw_diag_ce_download = false,741 .credit_size_workaround = false,742 .tx_stats_over_pktlog = false,743 .dynamic_sar_support = true,744 .hw_restart_disconnect = true,745 .use_fw_tx_credits = false,746 .delay_unmap_buffer = true,747 .mcast_frame_registration = false,748 },749};750 751static const char *const ath10k_core_fw_feature_str[] = {752 [ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX] = "wmi-mgmt-rx",753 [ATH10K_FW_FEATURE_WMI_10X] = "wmi-10.x",754 [ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX] = "has-wmi-mgmt-tx",755 [ATH10K_FW_FEATURE_NO_P2P] = "no-p2p",756 [ATH10K_FW_FEATURE_WMI_10_2] = "wmi-10.2",757 [ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT] = "multi-vif-ps",758 [ATH10K_FW_FEATURE_WOWLAN_SUPPORT] = "wowlan",759 [ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp",760 [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",761 [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",762 [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",763 [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",764 [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",765 [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",766 [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",767 [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",768 [ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",769 [ATH10K_FW_FEATURE_NO_PS] = "no-ps",770 [ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference",771 [ATH10K_FW_FEATURE_NON_BMI] = "non-bmi",772 [ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel",773 [ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate",774 [ATH10K_FW_FEATURE_IRAM_RECOVERY] = "iram-recovery",775};776 777static unsigned int ath10k_core_get_fw_feature_str(char *buf,778 size_t buf_len,779 enum ath10k_fw_features feat)780{781 /* make sure that ath10k_core_fw_feature_str[] gets updated */782 BUILD_BUG_ON(ARRAY_SIZE(ath10k_core_fw_feature_str) !=783 ATH10K_FW_FEATURE_COUNT);784 785 if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) ||786 WARN_ON(!ath10k_core_fw_feature_str[feat])) {787 return scnprintf(buf, buf_len, "bit%d", feat);788 }789 790 return scnprintf(buf, buf_len, "%s", ath10k_core_fw_feature_str[feat]);791}792 793void ath10k_core_get_fw_features_str(struct ath10k *ar,794 char *buf,795 size_t buf_len)796{797 size_t len = 0;798 int i;799 800 for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {801 if (test_bit(i, ar->normal_mode_fw.fw_file.fw_features)) {802 if (len > 0)803 len += scnprintf(buf + len, buf_len - len, ",");804 805 len += ath10k_core_get_fw_feature_str(buf + len,806 buf_len - len,807 i);808 }809 }810}811 812static void ath10k_send_suspend_complete(struct ath10k *ar)813{814 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot suspend complete\n");815 816 complete(&ar->target_suspend);817}818 819static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)820{821 bool mtu_workaround = ar->hw_params.credit_size_workaround;822 int ret;823 u32 param = 0;824 825 ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);826 if (ret)827 return ret;828 829 ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);830 if (ret)831 return ret;832 833 ret = ath10k_bmi_read32(ar, hi_acs_flags, ¶m);834 if (ret)835 return ret;836 837 param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;838 839 if (mode == ATH10K_FIRMWARE_MODE_NORMAL && !mtu_workaround)840 param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;841 else842 param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;843 844 if (mode == ATH10K_FIRMWARE_MODE_UTF)845 param &= ~HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;846 else847 param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;848 849 ret = ath10k_bmi_write32(ar, hi_acs_flags, param);850 if (ret)851 return ret;852 853 ret = ath10k_bmi_read32(ar, hi_option_flag2, ¶m);854 if (ret)855 return ret;856 857 param |= HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST;858 859 ret = ath10k_bmi_write32(ar, hi_option_flag2, param);860 if (ret)861 return ret;862 863 return 0;864}865 866static int ath10k_init_configure_target(struct ath10k *ar)867{868 u32 param_host;869 int ret;870 871 /* tell target which HTC version it is used*/872 ret = ath10k_bmi_write32(ar, hi_app_host_interest,873 HTC_PROTOCOL_VERSION);874 if (ret) {875 ath10k_err(ar, "settings HTC version failed\n");876 return ret;877 }878 879 /* set the firmware mode to STA/IBSS/AP */880 ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m_host);881 if (ret) {882 ath10k_err(ar, "setting firmware mode (1/2) failed\n");883 return ret;884 }885 886 /* TODO following parameters need to be re-visited. */887 /* num_device */888 param_host |= (1 << HI_OPTION_NUM_DEV_SHIFT);889 /* Firmware mode */890 /* FIXME: Why FW_MODE_AP ??.*/891 param_host |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT);892 /* mac_addr_method */893 param_host |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);894 /* firmware_bridge */895 param_host |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);896 /* fwsubmode */897 param_host |= (0 << HI_OPTION_FW_SUBMODE_SHIFT);898 899 ret = ath10k_bmi_write32(ar, hi_option_flag, param_host);900 if (ret) {901 ath10k_err(ar, "setting firmware mode (2/2) failed\n");902 return ret;903 }904 905 /* We do all byte-swapping on the host */906 ret = ath10k_bmi_write32(ar, hi_be, 0);907 if (ret) {908 ath10k_err(ar, "setting host CPU BE mode failed\n");909 return ret;910 }911 912 /* FW descriptor/Data swap flags */913 ret = ath10k_bmi_write32(ar, hi_fw_swap, 0);914 915 if (ret) {916 ath10k_err(ar, "setting FW data/desc swap flags failed\n");917 return ret;918 }919 920 /* Some devices have a special sanity check that verifies the PCI921 * Device ID is written to this host interest var. It is known to be922 * required to boot QCA6164.923 */924 ret = ath10k_bmi_write32(ar, hi_hci_uart_pwr_mgmt_params_ext,925 ar->dev_id);926 if (ret) {927 ath10k_err(ar, "failed to set pwr_mgmt_params: %d\n", ret);928 return ret;929 }930 931 return 0;932}933 934static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,935 const char *dir,936 const char *file)937{938 char filename[100];939 const struct firmware *fw;940 int ret;941 942 if (file == NULL)943 return ERR_PTR(-ENOENT);944 945 if (dir == NULL)946 dir = ".";947 948 if (ar->board_name) {949 snprintf(filename, sizeof(filename), "%s/%s/%s",950 dir, ar->board_name, file);951 ret = firmware_request_nowarn(&fw, filename, ar->dev);952 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",953 filename, ret);954 if (!ret)955 return fw;956 }957 958 snprintf(filename, sizeof(filename), "%s/%s", dir, file);959 ret = firmware_request_nowarn(&fw, filename, ar->dev);960 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",961 filename, ret);962 if (ret)963 return ERR_PTR(ret);964 965 return fw;966}967 968static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,969 size_t data_len)970{971 u32 board_data_size = ar->hw_params.fw.board_size;972 u32 board_ext_data_size = ar->hw_params.fw.board_ext_size;973 u32 board_ext_data_addr;974 int ret;975 976 ret = ath10k_bmi_read32(ar, hi_board_ext_data, &board_ext_data_addr);977 if (ret) {978 ath10k_err(ar, "could not read board ext data addr (%d)\n",979 ret);980 return ret;981 }982 983 ath10k_dbg(ar, ATH10K_DBG_BOOT,984 "boot push board extended data addr 0x%x\n",985 board_ext_data_addr);986 987 if (board_ext_data_addr == 0)988 return 0;989 990 if (data_len != (board_data_size + board_ext_data_size)) {991 ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",992 data_len, board_data_size, board_ext_data_size);993 return -EINVAL;994 }995 996 ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,997 data + board_data_size,998 board_ext_data_size);999 if (ret) {1000 ath10k_err(ar, "could not write board ext data (%d)\n", ret);1001 return ret;1002 }1003 1004 ret = ath10k_bmi_write32(ar, hi_board_ext_data_config,1005 (board_ext_data_size << 16) | 1);1006 if (ret) {1007 ath10k_err(ar, "could not write board ext data bit (%d)\n",1008 ret);1009 return ret;1010 }1011 1012 return 0;1013}1014 1015static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)1016{1017 u32 result, address;1018 u8 board_id, chip_id;1019 bool ext_bid_support;1020 int ret, bmi_board_id_param;1021 1022 address = ar->hw_params.patch_load_addr;1023 1024 if (!ar->normal_mode_fw.fw_file.otp_data ||1025 !ar->normal_mode_fw.fw_file.otp_len) {1026 ath10k_warn(ar,1027 "failed to retrieve board id because of invalid otp\n");1028 return -ENODATA;1029 }1030 1031 if (ar->id.bmi_ids_valid) {1032 ath10k_dbg(ar, ATH10K_DBG_BOOT,1033 "boot already acquired valid otp board id,skip download, board_id %d chip_id %d\n",1034 ar->id.bmi_board_id, ar->id.bmi_chip_id);1035 goto skip_otp_download;1036 }1037 1038 ath10k_dbg(ar, ATH10K_DBG_BOOT,1039 "boot upload otp to 0x%x len %zd for board id\n",1040 address, ar->normal_mode_fw.fw_file.otp_len);1041 1042 ret = ath10k_bmi_fast_download(ar, address,1043 ar->normal_mode_fw.fw_file.otp_data,1044 ar->normal_mode_fw.fw_file.otp_len);1045 if (ret) {1046 ath10k_err(ar, "could not write otp for board id check: %d\n",1047 ret);1048 return ret;1049 }1050 1051 if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||1052 ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||1053 ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)1054 bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID;1055 else1056 bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID;1057 1058 ret = ath10k_bmi_execute(ar, address, bmi_board_id_param, &result);1059 if (ret) {1060 ath10k_err(ar, "could not execute otp for board id check: %d\n",1061 ret);1062 return ret;1063 }1064 1065 board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);1066 chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP);1067 ext_bid_support = (result & ATH10K_BMI_EXT_BOARD_ID_SUPPORT);1068 1069 ath10k_dbg(ar, ATH10K_DBG_BOOT,1070 "boot get otp board id result 0x%08x board_id %d chip_id %d ext_bid_support %d\n",1071 result, board_id, chip_id, ext_bid_support);1072 1073 ar->id.ext_bid_supported = ext_bid_support;1074 1075 if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 ||1076 (board_id == 0)) {1077 ath10k_dbg(ar, ATH10K_DBG_BOOT,1078 "board id does not exist in otp, ignore it\n");1079 return -EOPNOTSUPP;1080 }1081 1082 ar->id.bmi_ids_valid = true;1083 ar->id.bmi_board_id = board_id;1084 ar->id.bmi_chip_id = chip_id;1085 1086skip_otp_download:1087 1088 return 0;1089}1090 1091static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data)1092{1093 struct ath10k *ar = data;1094 const char *bdf_ext;1095 const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC;1096 u8 bdf_enabled;1097 int i;1098 1099 if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE)1100 return;1101 1102 if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) {1103 ath10k_dbg(ar, ATH10K_DBG_BOOT,1104 "wrong smbios bdf ext type length (%d).\n",1105 hdr->length);1106 return;1107 }1108 1109 bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET);1110 if (!bdf_enabled) {1111 ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n");1112 return;1113 }1114 1115 /* Only one string exists (per spec) */1116 bdf_ext = (char *)hdr + hdr->length;1117 1118 if (memcmp(bdf_ext, magic, strlen(magic)) != 0) {1119 ath10k_dbg(ar, ATH10K_DBG_BOOT,1120 "bdf variant magic does not match.\n");1121 return;1122 }1123 1124 for (i = 0; i < strlen(bdf_ext); i++) {1125 if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) {1126 ath10k_dbg(ar, ATH10K_DBG_BOOT,1127 "bdf variant name contains non ascii chars.\n");1128 return;1129 }1130 }1131 1132 /* Copy extension name without magic suffix */1133 if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),1134 sizeof(ar->id.bdf_ext)) < 0) {1135 ath10k_dbg(ar, ATH10K_DBG_BOOT,1136 "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",1137 bdf_ext);1138 return;1139 }1140 1141 ath10k_dbg(ar, ATH10K_DBG_BOOT,1142 "found and validated bdf variant smbios_type 0x%x bdf %s\n",1143 ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext);1144}1145 1146static int ath10k_core_check_smbios(struct ath10k *ar)1147{1148 ar->id.bdf_ext[0] = '\0';1149 dmi_walk(ath10k_core_check_bdfext, ar);1150 1151 if (ar->id.bdf_ext[0] == '\0')1152 return -ENODATA;1153 1154 return 0;1155}1156 1157int ath10k_core_check_dt(struct ath10k *ar)1158{1159 struct device_node *node;1160 const char *variant = NULL;1161 1162 node = ar->dev->of_node;1163 if (!node)1164 return -ENOENT;1165 1166 of_property_read_string(node, "qcom,ath10k-calibration-variant",1167 &variant);1168 if (!variant)1169 return -ENODATA;1170 1171 if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0)1172 ath10k_dbg(ar, ATH10K_DBG_BOOT,1173 "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",1174 variant);1175 1176 return 0;1177}1178EXPORT_SYMBOL(ath10k_core_check_dt);1179 1180static int ath10k_download_fw(struct ath10k *ar)1181{1182 u32 address, data_len;1183 const void *data;1184 int ret;1185 struct pm_qos_request latency_qos;1186 1187 address = ar->hw_params.patch_load_addr;1188 1189 data = ar->running_fw->fw_file.firmware_data;1190 data_len = ar->running_fw->fw_file.firmware_len;1191 1192 ret = ath10k_swap_code_seg_configure(ar, &ar->running_fw->fw_file);1193 if (ret) {1194 ath10k_err(ar, "failed to configure fw code swap: %d\n",1195 ret);1196 return ret;1197 }1198 1199 ath10k_dbg(ar, ATH10K_DBG_BOOT,1200 "boot uploading firmware image %pK len %d\n",1201 data, data_len);1202 1203 /* Check if device supports to download firmware via1204 * diag copy engine. Downloading firmware via diag CE1205 * greatly reduces the time to download firmware.1206 */1207 if (ar->hw_params.fw_diag_ce_download) {1208 ret = ath10k_hw_diag_fast_download(ar, address,1209 data, data_len);1210 if (ret == 0)1211 /* firmware upload via diag ce was successful */1212 return 0;1213 1214 ath10k_warn(ar,1215 "failed to upload firmware via diag ce, trying BMI: %d",1216 ret);1217 }1218 1219 memset(&latency_qos, 0, sizeof(latency_qos));1220 cpu_latency_qos_add_request(&latency_qos, 0);1221 1222 ret = ath10k_bmi_fast_download(ar, address, data, data_len);1223 1224 cpu_latency_qos_remove_request(&latency_qos);1225 1226 return ret;1227}1228 1229void ath10k_core_free_board_files(struct ath10k *ar)1230{1231 if (!IS_ERR(ar->normal_mode_fw.board))1232 release_firmware(ar->normal_mode_fw.board);1233 1234 if (!IS_ERR(ar->normal_mode_fw.ext_board))1235 release_firmware(ar->normal_mode_fw.ext_board);1236 1237 ar->normal_mode_fw.board = NULL;1238 ar->normal_mode_fw.board_data = NULL;1239 ar->normal_mode_fw.board_len = 0;1240 ar->normal_mode_fw.ext_board = NULL;1241 ar->normal_mode_fw.ext_board_data = NULL;1242 ar->normal_mode_fw.ext_board_len = 0;1243}1244EXPORT_SYMBOL(ath10k_core_free_board_files);1245 1246static void ath10k_core_free_firmware_files(struct ath10k *ar)1247{1248 if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware))1249 release_firmware(ar->normal_mode_fw.fw_file.firmware);1250 1251 if (!IS_ERR(ar->cal_file))1252 release_firmware(ar->cal_file);1253 1254 if (!IS_ERR(ar->pre_cal_file))1255 release_firmware(ar->pre_cal_file);1256 1257 ath10k_swap_code_seg_release(ar, &ar->normal_mode_fw.fw_file);1258 1259 ar->normal_mode_fw.fw_file.otp_data = NULL;1260 ar->normal_mode_fw.fw_file.otp_len = 0;1261 1262 ar->normal_mode_fw.fw_file.firmware = NULL;1263 ar->normal_mode_fw.fw_file.firmware_data = NULL;1264 ar->normal_mode_fw.fw_file.firmware_len = 0;1265 1266 ar->cal_file = NULL;1267 ar->pre_cal_file = NULL;1268}1269 1270static int ath10k_fetch_cal_file(struct ath10k *ar)1271{1272 char filename[100];1273 1274 /* pre-cal-<bus>-<id>.bin */1275 scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin",1276 ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));1277 1278 ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);1279 if (!IS_ERR(ar->pre_cal_file))1280 goto success;1281 1282 /* cal-<bus>-<id>.bin */1283 scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",1284 ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));1285 1286 ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);1287 if (IS_ERR(ar->cal_file))1288 /* calibration file is optional, don't print any warnings */1289 return PTR_ERR(ar->cal_file);1290success:1291 ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",1292 ATH10K_FW_DIR, filename);1293 1294 return 0;1295}1296 1297static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type)1298{1299 const struct firmware *fw;1300 char boardname[100];1301 1302 if (bd_ie_type == ATH10K_BD_IE_BOARD) {1303 scnprintf(boardname, sizeof(boardname), "board-%s-%s.bin",1304 ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));1305 1306 ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,1307 ar->hw_params.fw.dir,1308 boardname);1309 if (IS_ERR(ar->normal_mode_fw.board)) {1310 fw = ath10k_fetch_fw_file(ar,1311 ar->hw_params.fw.dir,1312 ATH10K_BOARD_DATA_FILE);1313 ar->normal_mode_fw.board = fw;1314 }1315 1316 if (IS_ERR(ar->normal_mode_fw.board))1317 return PTR_ERR(ar->normal_mode_fw.board);1318 1319 ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;1320 ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;1321 } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {1322 fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,1323 ATH10K_EBOARD_DATA_FILE);1324 ar->normal_mode_fw.ext_board = fw;1325 if (IS_ERR(ar->normal_mode_fw.ext_board))1326 return PTR_ERR(ar->normal_mode_fw.ext_board);1327 1328 ar->normal_mode_fw.ext_board_data = ar->normal_mode_fw.ext_board->data;1329 ar->normal_mode_fw.ext_board_len = ar->normal_mode_fw.ext_board->size;1330 }1331 1332 return 0;1333}1334 1335static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,1336 const void *buf, size_t buf_len,1337 const char *boardname,1338 int bd_ie_type)1339{1340 const struct ath10k_fw_ie *hdr;1341 bool name_match_found;1342 int ret, board_ie_id;1343 size_t board_ie_len;1344 const void *board_ie_data;1345 1346 name_match_found = false;1347 1348 /* go through ATH10K_BD_IE_BOARD_ elements */1349 while (buf_len > sizeof(struct ath10k_fw_ie)) {1350 hdr = buf;1351 board_ie_id = le32_to_cpu(hdr->id);1352 board_ie_len = le32_to_cpu(hdr->len);1353 board_ie_data = hdr->data;1354 1355 buf_len -= sizeof(*hdr);1356 buf += sizeof(*hdr);1357 1358 if (buf_len < ALIGN(board_ie_len, 4)) {1359 ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n",1360 buf_len, ALIGN(board_ie_len, 4));1361 ret = -EINVAL;1362 goto out;1363 }1364 1365 switch (board_ie_id) {1366 case ATH10K_BD_IE_BOARD_NAME:1367 ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "",1368 board_ie_data, board_ie_len);1369 1370 if (board_ie_len != strlen(boardname))1371 break;1372 1373 ret = memcmp(board_ie_data, boardname, strlen(boardname));1374 if (ret)1375 break;1376 1377 name_match_found = true;1378 ath10k_dbg(ar, ATH10K_DBG_BOOT,1379 "boot found match for name '%s'",1380 boardname);1381 break;1382 case ATH10K_BD_IE_BOARD_DATA:1383 if (!name_match_found)1384 /* no match found */1385 break;1386 1387 if (bd_ie_type == ATH10K_BD_IE_BOARD) {1388 ath10k_dbg(ar, ATH10K_DBG_BOOT,1389 "boot found board data for '%s'",1390 boardname);1391 1392 ar->normal_mode_fw.board_data = board_ie_data;1393 ar->normal_mode_fw.board_len = board_ie_len;1394 } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {1395 ath10k_dbg(ar, ATH10K_DBG_BOOT,1396 "boot found eboard data for '%s'",1397 boardname);1398 1399 ar->normal_mode_fw.ext_board_data = board_ie_data;1400 ar->normal_mode_fw.ext_board_len = board_ie_len;1401 }1402 1403 ret = 0;1404 goto out;1405 default:1406 ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n",1407 board_ie_id);1408 break;1409 }1410 1411 /* jump over the padding */1412 board_ie_len = ALIGN(board_ie_len, 4);1413 1414 buf_len -= board_ie_len;1415 buf += board_ie_len;1416 }1417 1418 /* no match found */1419 ret = -ENOENT;1420 1421out:1422 return ret;1423}1424 1425static int ath10k_core_search_bd(struct ath10k *ar,1426 const char *boardname,1427 const u8 *data,1428 size_t len)1429{1430 size_t ie_len;1431 struct ath10k_fw_ie *hdr;1432 int ret = -ENOENT, ie_id;1433 1434 while (len > sizeof(struct ath10k_fw_ie)) {1435 hdr = (struct ath10k_fw_ie *)data;1436 ie_id = le32_to_cpu(hdr->id);1437 ie_len = le32_to_cpu(hdr->len);1438 1439 len -= sizeof(*hdr);1440 data = hdr->data;1441 1442 if (len < ALIGN(ie_len, 4)) {1443 ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",1444 ie_id, ie_len, len);1445 return -EINVAL;1446 }1447 1448 switch (ie_id) {1449 case ATH10K_BD_IE_BOARD:1450 ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,1451 boardname,1452 ATH10K_BD_IE_BOARD);1453 if (ret == -ENOENT)1454 /* no match found, continue */1455 break;1456 1457 /* either found or error, so stop searching */1458 goto out;1459 case ATH10K_BD_IE_BOARD_EXT:1460 ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,1461 boardname,1462 ATH10K_BD_IE_BOARD_EXT);1463 if (ret == -ENOENT)1464 /* no match found, continue */1465 break;1466 1467 /* either found or error, so stop searching */1468 goto out;1469 }1470 1471 /* jump over the padding */1472 ie_len = ALIGN(ie_len, 4);1473 1474 len -= ie_len;1475 data += ie_len;1476 }1477 1478out:1479 /* return result of parse_bd_ie_board() or -ENOENT */1480 return ret;1481}1482 1483static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,1484 const char *boardname,1485 const char *fallback_boardname1,1486 const char *fallback_boardname2,1487 const char *filename)1488{1489 size_t len, magic_len;1490 const u8 *data;1491 int ret;1492 1493 /* Skip if already fetched during board data download */1494 if (!ar->normal_mode_fw.board)1495 ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,1496 ar->hw_params.fw.dir,1497 filename);1498 if (IS_ERR(ar->normal_mode_fw.board))1499 return PTR_ERR(ar->normal_mode_fw.board);1500 1501 data = ar->normal_mode_fw.board->data;1502 len = ar->normal_mode_fw.board->size;1503 1504 /* magic has extra null byte padded */1505 magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;1506 if (len < magic_len) {1507 ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n",1508 ar->hw_params.fw.dir, filename, len);1509 ret = -EINVAL;1510 goto err;1511 }1512 1513 if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) {1514 ath10k_err(ar, "found invalid board magic\n");1515 ret = -EINVAL;1516 goto err;1517 }1518 1519 /* magic is padded to 4 bytes */1520 magic_len = ALIGN(magic_len, 4);1521 if (len < magic_len) {1522 ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n",1523 ar->hw_params.fw.dir, filename, len);1524 ret = -EINVAL;1525 goto err;1526 }1527 1528 data += magic_len;1529 len -= magic_len;1530 1531 /* attempt to find boardname in the IE list */1532 ret = ath10k_core_search_bd(ar, boardname, data, len);1533 1534 /* if we didn't find it and have a fallback name, try that */1535 if (ret == -ENOENT && fallback_boardname1)1536 ret = ath10k_core_search_bd(ar, fallback_boardname1, data, len);1537 1538 if (ret == -ENOENT && fallback_boardname2)1539 ret = ath10k_core_search_bd(ar, fallback_boardname2, data, len);1540 1541 if (ret == -ENOENT) {1542 ath10k_err(ar,1543 "failed to fetch board data for %s from %s/%s\n",1544 boardname, ar->hw_params.fw.dir, filename);1545 ret = -ENODATA;1546 }1547 1548 if (ret)1549 goto err;1550 1551 return 0;1552 1553err:1554 ath10k_core_free_board_files(ar);1555 return ret;1556}1557 1558static int ath10k_core_create_board_name(struct ath10k *ar, char *name,1559 size_t name_len, bool with_variant,1560 bool with_chip_id)1561{1562 /* strlen(',variant=') + strlen(ar->id.bdf_ext) */1563 char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };1564 1565 if (with_variant && ar->id.bdf_ext[0] != '\0')1566 scnprintf(variant, sizeof(variant), ",variant=%s",1567 ar->id.bdf_ext);1568 1569 if (ar->id.bmi_ids_valid) {1570 scnprintf(name, name_len,1571 "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",1572 ath10k_bus_str(ar->hif.bus),1573 ar->id.bmi_chip_id,1574 ar->id.bmi_board_id, variant);1575 goto out;1576 }1577 1578 if (ar->id.qmi_ids_valid) {1579 if (with_chip_id)1580 scnprintf(name, name_len,1581 "bus=%s,qmi-board-id=%x,qmi-chip-id=%x%s",1582 ath10k_bus_str(ar->hif.bus),1583 ar->id.qmi_board_id, ar->id.qmi_chip_id,1584 variant);1585 else1586 scnprintf(name, name_len,1587 "bus=%s,qmi-board-id=%x",1588 ath10k_bus_str(ar->hif.bus),1589 ar->id.qmi_board_id);1590 goto out;1591 }1592 1593 scnprintf(name, name_len,1594 "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",1595 ath10k_bus_str(ar->hif.bus),1596 ar->id.vendor, ar->id.device,1597 ar->id.subsystem_vendor, ar->id.subsystem_device, variant);1598out:1599 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);1600 1601 return 0;1602}1603 1604static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name,1605 size_t name_len)1606{1607 if (ar->id.bmi_ids_valid) {1608 scnprintf(name, name_len,1609 "bus=%s,bmi-chip-id=%d,bmi-eboard-id=%d",1610 ath10k_bus_str(ar->hif.bus),1611 ar->id.bmi_chip_id,1612 ar->id.bmi_eboard_id);1613 1614 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using eboard name '%s'\n", name);1615 return 0;1616 }1617 /* Fallback if returned board id is zero */1618 return -1;1619}1620 1621int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type)1622{1623 char boardname[100], fallback_boardname1[100], fallback_boardname2[100];1624 int ret;1625 1626 if (bd_ie_type == ATH10K_BD_IE_BOARD) {1627 /* With variant and chip id */1628 ret = ath10k_core_create_board_name(ar, boardname,1629 sizeof(boardname), true,1630 true);1631 if (ret) {1632 ath10k_err(ar, "failed to create board name: %d", ret);1633 return ret;1634 }1635 1636 /* Without variant and only chip-id */1637 ret = ath10k_core_create_board_name(ar, fallback_boardname1,1638 sizeof(boardname), false,1639 true);1640 if (ret) {1641 ath10k_err(ar, "failed to create 1st fallback board name: %d",1642 ret);1643 return ret;1644 }1645 1646 /* Without variant and without chip-id */1647 ret = ath10k_core_create_board_name(ar, fallback_boardname2,1648 sizeof(boardname), false,1649 false);1650 if (ret) {1651 ath10k_err(ar, "failed to create 2nd fallback board name: %d",1652 ret);1653 return ret;1654 }1655 } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) {1656 ret = ath10k_core_create_eboard_name(ar, boardname,1657 sizeof(boardname));1658 if (ret) {1659 ath10k_err(ar, "fallback to eboard.bin since board id 0");1660 goto fallback;1661 }1662 }1663 1664 ar->bd_api = 2;1665 ret = ath10k_core_fetch_board_data_api_n(ar, boardname,1666 fallback_boardname1,1667 fallback_boardname2,1668 ATH10K_BOARD_API2_FILE);1669 if (!ret)1670 goto success;1671 1672fallback:1673 ar->bd_api = 1;1674 ret = ath10k_core_fetch_board_data_api_1(ar, bd_ie_type);1675 if (ret) {1676 ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",1677 ar->hw_params.fw.dir);1678 return ret;1679 }1680 1681success:1682 ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api);1683 return 0;1684}1685EXPORT_SYMBOL(ath10k_core_fetch_board_file);1686 1687static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar)1688{1689 u32 result, address;1690 u8 ext_board_id;1691 int ret;1692 1693 address = ar->hw_params.patch_load_addr;1694 1695 if (!ar->normal_mode_fw.fw_file.otp_data ||1696 !ar->normal_mode_fw.fw_file.otp_len) {1697 ath10k_warn(ar,1698 "failed to retrieve extended board id due to otp binary missing\n");1699 return -ENODATA;1700 }1701 1702 ath10k_dbg(ar, ATH10K_DBG_BOOT,1703 "boot upload otp to 0x%x len %zd for ext board id\n",1704 address, ar->normal_mode_fw.fw_file.otp_len);1705 1706 ret = ath10k_bmi_fast_download(ar, address,1707 ar->normal_mode_fw.fw_file.otp_data,1708 ar->normal_mode_fw.fw_file.otp_len);1709 if (ret) {1710 ath10k_err(ar, "could not write otp for ext board id check: %d\n",1711 ret);1712 return ret;1713 }1714 1715 ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EXT_BOARD_ID, &result);1716 if (ret) {1717 ath10k_err(ar, "could not execute otp for ext board id check: %d\n",1718 ret);1719 return ret;1720 }1721 1722 if (!result) {1723 ath10k_dbg(ar, ATH10K_DBG_BOOT,1724 "ext board id does not exist in otp, ignore it\n");1725 return -EOPNOTSUPP;1726 }1727 1728 ext_board_id = result & ATH10K_BMI_EBOARD_ID_STATUS_MASK;1729 1730 ath10k_dbg(ar, ATH10K_DBG_BOOT,1731 "boot get otp ext board id result 0x%08x ext_board_id %d\n",1732 result, ext_board_id);1733 1734 ar->id.bmi_eboard_id = ext_board_id;1735 1736 return 0;1737}1738 1739static int ath10k_download_board_data(struct ath10k *ar, const void *data,1740 size_t data_len)1741{1742 u32 board_data_size = ar->hw_params.fw.board_size;1743 u32 eboard_data_size = ar->hw_params.fw.ext_board_size;1744 u32 board_address;1745 u32 ext_board_address;1746 int ret;1747 1748 ret = ath10k_push_board_ext_data(ar, data, data_len);1749 if (ret) {1750 ath10k_err(ar, "could not push board ext data (%d)\n", ret);1751 goto exit;1752 }1753 1754 ret = ath10k_bmi_read32(ar, hi_board_data, &board_address);1755 if (ret) {1756 ath10k_err(ar, "could not read board data addr (%d)\n", ret);1757 goto exit;1758 }1759 1760 ret = ath10k_bmi_write_memory(ar, board_address, data,1761 min_t(u32, board_data_size,1762 data_len));1763 if (ret) {1764 ath10k_err(ar, "could not write board data (%d)\n", ret);1765 goto exit;1766 }1767 1768 ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);1769 if (ret) {1770 ath10k_err(ar, "could not write board data bit (%d)\n", ret);1771 goto exit;1772 }1773 1774 if (!ar->id.ext_bid_supported)1775 goto exit;1776 1777 /* Extended board data download */1778 ret = ath10k_core_get_ext_board_id_from_otp(ar);1779 if (ret == -EOPNOTSUPP) {1780 /* Not fetching ext_board_data if ext board id is 0 */1781 ath10k_dbg(ar, ATH10K_DBG_BOOT, "otp returned ext board id 0\n");1782 return 0;1783 } else if (ret) {1784 ath10k_err(ar, "failed to get extended board id: %d\n", ret);1785 goto exit;1786 }1787 1788 ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD_EXT);1789 if (ret)1790 goto exit;1791 1792 if (ar->normal_mode_fw.ext_board_data) {1793 ext_board_address = board_address + EXT_BOARD_ADDRESS_OFFSET;1794 ath10k_dbg(ar, ATH10K_DBG_BOOT,1795 "boot writing ext board data to addr 0x%x",1796 ext_board_address);1797 ret = ath10k_bmi_write_memory(ar, ext_board_address,1798 ar->normal_mode_fw.ext_board_data,1799 min_t(u32, eboard_data_size, data_len));1800 if (ret)1801 ath10k_err(ar, "failed to write ext board data: %d\n", ret);1802 }1803 1804exit:1805 return ret;1806}1807 1808static int ath10k_download_and_run_otp(struct ath10k *ar)1809{1810 u32 result, address = ar->hw_params.patch_load_addr;1811 u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;1812 int ret;1813 1814 ret = ath10k_download_board_data(ar,1815 ar->running_fw->board_data,1816 ar->running_fw->board_len);1817 if (ret) {1818 ath10k_err(ar, "failed to download board data: %d\n", ret);1819 return ret;1820 }1821 1822 /* OTP is optional */1823 1824 if (!ar->running_fw->fw_file.otp_data ||1825 !ar->running_fw->fw_file.otp_len) {1826 ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n",1827 ar->running_fw->fw_file.otp_data,1828 ar->running_fw->fw_file.otp_len);1829 return 0;1830 }1831 1832 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",1833 address, ar->running_fw->fw_file.otp_len);1834 1835 ret = ath10k_bmi_fast_download(ar, address,1836 ar->running_fw->fw_file.otp_data,1837 ar->running_fw->fw_file.otp_len);1838 if (ret) {1839 ath10k_err(ar, "could not write otp (%d)\n", ret);1840 return ret;1841 }1842 1843 /* As of now pre-cal is valid for 10_4 variants */1844 if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT ||1845 ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE ||1846 ar->cal_mode == ATH10K_PRE_CAL_MODE_NVMEM)1847 bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL;1848 1849 ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);1850 if (ret) {1851 ath10k_err(ar, "could not execute otp (%d)\n", ret);1852 return ret;1853 }1854 1855 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);1856 1857 if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,1858 ar->running_fw->fw_file.fw_features)) &&1859 result != 0) {1860 ath10k_err(ar, "otp calibration failed: %d", result);1861 return -EINVAL;1862 }1863 1864 return 0;1865}1866 1867static int ath10k_download_cal_file(struct ath10k *ar,1868 const struct firmware *file)1869{1870 int ret;1871 1872 if (!file)1873 return -ENOENT;1874 1875 if (IS_ERR(file))1876 return PTR_ERR(file);1877 1878 ret = ath10k_download_board_data(ar, file->data, file->size);1879 if (ret) {1880 ath10k_err(ar, "failed to download cal_file data: %d\n", ret);1881 return ret;1882 }1883 1884 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");1885 1886 return 0;1887}1888 1889static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)1890{1891 struct device_node *node;1892 int data_len;1893 void *data;1894 int ret;1895 1896 node = ar->dev->of_node;1897 if (!node)1898 /* Device Tree is optional, don't print any warnings if1899 * there's no node for ath10k.1900 */1901 return -ENOENT;1902 1903 if (!of_get_property(node, dt_name, &data_len)) {1904 /* The calibration data node is optional */1905 return -ENOENT;1906 }1907 1908 if (data_len != ar->hw_params.cal_data_len) {1909 ath10k_warn(ar, "invalid calibration data length in DT: %d\n",1910 data_len);1911 ret = -EMSGSIZE;1912 goto out;1913 }1914 1915 data = kmalloc(data_len, GFP_KERNEL);1916 if (!data) {1917 ret = -ENOMEM;1918 goto out;1919 }1920 1921 ret = of_property_read_u8_array(node, dt_name, data, data_len);1922 if (ret) {1923 ath10k_warn(ar, "failed to read calibration data from DT: %d\n",1924 ret);1925 goto out_free;1926 }1927 1928 ret = ath10k_download_board_data(ar, data, data_len);1929 if (ret) {1930 ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",1931 ret);1932 goto out_free;1933 }1934 1935 ret = 0;1936 1937out_free:1938 kfree(data);1939 1940out:1941 return ret;1942}1943 1944static int ath10k_download_cal_eeprom(struct ath10k *ar)1945{1946 size_t data_len;1947 void *data = NULL;1948 int ret;1949 1950 ret = ath10k_hif_fetch_cal_eeprom(ar, &data, &data_len);1951 if (ret) {1952 if (ret != -EOPNOTSUPP)1953 ath10k_warn(ar, "failed to read calibration data from EEPROM: %d\n",1954 ret);1955 goto out_free;1956 }1957 1958 ret = ath10k_download_board_data(ar, data, data_len);1959 if (ret) {1960 ath10k_warn(ar, "failed to download calibration data from EEPROM: %d\n",1961 ret);1962 goto out_free;1963 }1964 1965 ret = 0;1966 1967out_free:1968 kfree(data);1969 1970 return ret;1971}1972 1973static int ath10k_download_cal_nvmem(struct ath10k *ar, const char *cell_name)1974{1975 struct nvmem_cell *cell;1976 void *buf;1977 size_t len;1978 int ret;1979 1980 cell = devm_nvmem_cell_get(ar->dev, cell_name);1981 if (IS_ERR(cell)) {1982 ret = PTR_ERR(cell);1983 return ret;1984 }1985 1986 buf = nvmem_cell_read(cell, &len);1987 if (IS_ERR(buf))1988 return PTR_ERR(buf);1989 1990 if (ar->hw_params.cal_data_len != len) {1991 kfree(buf);1992 ath10k_warn(ar, "invalid calibration data length in nvmem-cell '%s': %zu != %u\n",1993 cell_name, len, ar->hw_params.cal_data_len);1994 return -EMSGSIZE;1995 }1996 1997 ret = ath10k_download_board_data(ar, buf, len);1998 kfree(buf);1999 if (ret)2000 ath10k_warn(ar, "failed to download calibration data from nvmem-cell '%s': %d\n",2001 cell_name, ret);2002 2003 return ret;2004}2005 2006int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,2007 struct ath10k_fw_file *fw_file)2008{2009 size_t magic_len, len, ie_len;2010 int ie_id, i, index, bit, ret;2011 struct ath10k_fw_ie *hdr;2012 const u8 *data;2013 __le32 *timestamp, *version;2014 2015 /* first fetch the firmware file (firmware-*.bin) */2016 fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,2017 name);2018 if (IS_ERR(fw_file->firmware))2019 return PTR_ERR(fw_file->firmware);2020 2021 data = fw_file->firmware->data;2022 len = fw_file->firmware->size;2023 2024 /* magic also includes the null byte, check that as well */2025 magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;2026 2027 if (len < magic_len) {2028 ath10k_err(ar, "firmware file '%s/%s' too small to contain magic: %zu\n",2029 ar->hw_params.fw.dir, name, len);2030 ret = -EINVAL;2031 goto err;2032 }2033 2034 if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {2035 ath10k_err(ar, "invalid firmware magic\n");2036 ret = -EINVAL;2037 goto err;2038 }2039 2040 /* jump over the padding */2041 magic_len = ALIGN(magic_len, 4);2042 2043 len -= magic_len;2044 data += magic_len;2045 2046 /* loop elements */2047 while (len > sizeof(struct ath10k_fw_ie)) {2048 hdr = (struct ath10k_fw_ie *)data;2049 2050 ie_id = le32_to_cpu(hdr->id);2051 ie_len = le32_to_cpu(hdr->len);2052 2053 len -= sizeof(*hdr);2054 data += sizeof(*hdr);2055 2056 if (len < ie_len) {2057 ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",2058 ie_id, len, ie_len);2059 ret = -EINVAL;2060 goto err;2061 }2062 2063 switch (ie_id) {2064 case ATH10K_FW_IE_FW_VERSION:2065 if (ie_len > sizeof(fw_file->fw_version) - 1)2066 break;2067 2068 memcpy(fw_file->fw_version, data, ie_len);2069 fw_file->fw_version[ie_len] = '\0';2070 2071 ath10k_dbg(ar, ATH10K_DBG_BOOT,2072 "found fw version %s\n",2073 fw_file->fw_version);2074 break;2075 case ATH10K_FW_IE_TIMESTAMP:2076 if (ie_len != sizeof(u32))2077 break;2078 2079 timestamp = (__le32 *)data;2080 2081 ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw timestamp %d\n",2082 le32_to_cpup(timestamp));2083 break;2084 case ATH10K_FW_IE_FEATURES:2085 ath10k_dbg(ar, ATH10K_DBG_BOOT,2086 "found firmware features ie (%zd B)\n",2087 ie_len);2088 2089 for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {2090 index = i / 8;2091 bit = i % 8;2092 2093 if (index == ie_len)2094 break;2095 2096 if (data[index] & (1 << bit)) {2097 ath10k_dbg(ar, ATH10K_DBG_BOOT,2098 "Enabling feature bit: %i\n",2099 i);2100 __set_bit(i, fw_file->fw_features);2101 }2102 }2103 2104 ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "",2105 fw_file->fw_features,2106 sizeof(fw_file->fw_features));2107 break;2108 case ATH10K_FW_IE_FW_IMAGE:2109 ath10k_dbg(ar, ATH10K_DBG_BOOT,2110 "found fw image ie (%zd B)\n",2111 ie_len);2112 2113 fw_file->firmware_data = data;2114 fw_file->firmware_len = ie_len;2115 2116 break;2117 case ATH10K_FW_IE_OTP_IMAGE:2118 ath10k_dbg(ar, ATH10K_DBG_BOOT,2119 "found otp image ie (%zd B)\n",2120 ie_len);2121 2122 fw_file->otp_data = data;2123 fw_file->otp_len = ie_len;2124 2125 break;2126 case ATH10K_FW_IE_WMI_OP_VERSION:2127 if (ie_len != sizeof(u32))2128 break;2129 2130 version = (__le32 *)data;2131 2132 fw_file->wmi_op_version = le32_to_cpup(version);2133 2134 ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",2135 fw_file->wmi_op_version);2136 break;2137 case ATH10K_FW_IE_HTT_OP_VERSION:2138 if (ie_len != sizeof(u32))2139 break;2140 2141 version = (__le32 *)data;2142 2143 fw_file->htt_op_version = le32_to_cpup(version);2144 2145 ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n",2146 fw_file->htt_op_version);2147 break;2148 case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE:2149 ath10k_dbg(ar, ATH10K_DBG_BOOT,2150 "found fw code swap image ie (%zd B)\n",2151 ie_len);2152 fw_file->codeswap_data = data;2153 fw_file->codeswap_len = ie_len;2154 break;2155 default:2156 ath10k_warn(ar, "Unknown FW IE: %u\n",2157 le32_to_cpu(hdr->id));2158 break;2159 }2160 2161 /* jump over the padding */2162 ie_len = ALIGN(ie_len, 4);2163 2164 len -= ie_len;2165 data += ie_len;2166 }2167 2168 if (!test_bit(ATH10K_FW_FEATURE_NON_BMI, fw_file->fw_features) &&2169 (!fw_file->firmware_data || !fw_file->firmware_len)) {2170 ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",2171 ar->hw_params.fw.dir, name);2172 ret = -ENOMEDIUM;2173 goto err;2174 }2175 2176 return 0;2177 2178err:2179 ath10k_core_free_firmware_files(ar);2180 return ret;2181}2182 2183static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name,2184 size_t fw_name_len, int fw_api)2185{2186 switch (ar->hif.bus) {2187 case ATH10K_BUS_SDIO:2188 case ATH10K_BUS_USB:2189 scnprintf(fw_name, fw_name_len, "%s-%s-%d.bin",2190 ATH10K_FW_FILE_BASE, ath10k_bus_str(ar->hif.bus),2191 fw_api);2192 break;2193 case ATH10K_BUS_PCI:2194 case ATH10K_BUS_AHB:2195 case ATH10K_BUS_SNOC:2196 scnprintf(fw_name, fw_name_len, "%s-%d.bin",2197 ATH10K_FW_FILE_BASE, fw_api);2198 break;2199 }2200}2201 2202static int ath10k_core_fetch_firmware_files(struct ath10k *ar)2203{2204 int ret, i;2205 char fw_name[100];2206 2207 /* calibration file is optional, don't check for any errors */2208 ath10k_fetch_cal_file(ar);2209 2210 for (i = ATH10K_FW_API_MAX; i >= ATH10K_FW_API_MIN; i--) {2211 ar->fw_api = i;2212 ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n",2213 ar->fw_api);2214 2215 ath10k_core_get_fw_name(ar, fw_name, sizeof(fw_name), ar->fw_api);2216 ret = ath10k_core_fetch_firmware_api_n(ar, fw_name,2217 &ar->normal_mode_fw.fw_file);2218 if (!ret)2219 goto success;2220 }2221 2222 /* we end up here if we couldn't fetch any firmware */2223 2224 ath10k_err(ar, "Failed to find firmware-N.bin (N between %d and %d) from %s: %d",2225 ATH10K_FW_API_MIN, ATH10K_FW_API_MAX, ar->hw_params.fw.dir,2226 ret);2227 2228 return ret;2229 2230success:2231 ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);2232 2233 return 0;2234}2235 2236static int ath10k_core_pre_cal_download(struct ath10k *ar)2237{2238 int ret;2239 2240 ret = ath10k_download_cal_nvmem(ar, "pre-calibration");2241 if (ret == 0) {2242 ar->cal_mode = ATH10K_PRE_CAL_MODE_NVMEM;2243 goto success;2244 } else if (ret == -EPROBE_DEFER) {2245 return ret;2246 }2247 2248 ath10k_dbg(ar, ATH10K_DBG_BOOT,2249 "boot did not find a pre-calibration nvmem-cell, try file next: %d\n",2250 ret);2251 2252 ret = ath10k_download_cal_file(ar, ar->pre_cal_file);2253 if (ret == 0) {2254 ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;2255 goto success;2256 }2257 2258 ath10k_dbg(ar, ATH10K_DBG_BOOT,2259 "boot did not find a pre calibration file, try DT next: %d\n",2260 ret);2261 2262 ret = ath10k_download_cal_dt(ar, "qcom,ath10k-pre-calibration-data");2263 if (ret) {2264 ath10k_dbg(ar, ATH10K_DBG_BOOT,2265 "unable to load pre cal data from DT: %d\n", ret);2266 return ret;2267 }2268 ar->cal_mode = ATH10K_PRE_CAL_MODE_DT;2269 2270success:2271 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",2272 ath10k_cal_mode_str(ar->cal_mode));2273 2274 return 0;2275}2276 2277static int ath10k_core_pre_cal_config(struct ath10k *ar)2278{2279 int ret;2280 2281 ret = ath10k_core_pre_cal_download(ar);2282 if (ret) {2283 ath10k_dbg(ar, ATH10K_DBG_BOOT,2284 "failed to load pre cal data: %d\n", ret);2285 return ret;2286 }2287 2288 ret = ath10k_core_get_board_id_from_otp(ar);2289 if (ret) {2290 ath10k_err(ar, "failed to get board id: %d\n", ret);2291 return ret;2292 }2293 2294 ret = ath10k_download_and_run_otp(ar);2295 if (ret) {2296 ath10k_err(ar, "failed to run otp: %d\n", ret);2297 return ret;2298 }2299 2300 ath10k_dbg(ar, ATH10K_DBG_BOOT,2301 "pre cal configuration done successfully\n");2302 2303 return 0;2304}2305 2306static int ath10k_download_cal_data(struct ath10k *ar)2307{2308 int ret;2309 2310 ret = ath10k_core_pre_cal_config(ar);2311 if (ret == 0)2312 return 0;2313 2314 ath10k_dbg(ar, ATH10K_DBG_BOOT,2315 "pre cal download procedure failed, try cal file: %d\n",2316 ret);2317 2318 ret = ath10k_download_cal_nvmem(ar, "calibration");2319 if (ret == 0) {2320 ar->cal_mode = ATH10K_CAL_MODE_NVMEM;2321 goto done;2322 } else if (ret == -EPROBE_DEFER) {2323 return ret;2324 }2325 2326 ath10k_dbg(ar, ATH10K_DBG_BOOT,2327 "boot did not find a calibration nvmem-cell, try file next: %d\n",2328 ret);2329 2330 ret = ath10k_download_cal_file(ar, ar->cal_file);2331 if (ret == 0) {2332 ar->cal_mode = ATH10K_CAL_MODE_FILE;2333 goto done;2334 }2335 2336 ath10k_dbg(ar, ATH10K_DBG_BOOT,2337 "boot did not find a calibration file, try DT next: %d\n",2338 ret);2339 2340 ret = ath10k_download_cal_dt(ar, "qcom,ath10k-calibration-data");2341 if (ret == 0) {2342 ar->cal_mode = ATH10K_CAL_MODE_DT;2343 goto done;2344 }2345 2346 ath10k_dbg(ar, ATH10K_DBG_BOOT,2347 "boot did not find DT entry, try target EEPROM next: %d\n",2348 ret);2349 2350 ret = ath10k_download_cal_eeprom(ar);2351 if (ret == 0) {2352 ar->cal_mode = ATH10K_CAL_MODE_EEPROM;2353 goto done;2354 }2355 2356 ath10k_dbg(ar, ATH10K_DBG_BOOT,2357 "boot did not find target EEPROM entry, try OTP next: %d\n",2358 ret);2359 2360 ret = ath10k_download_and_run_otp(ar);2361 if (ret) {2362 ath10k_err(ar, "failed to run otp: %d\n", ret);2363 return ret;2364 }2365 2366 ar->cal_mode = ATH10K_CAL_MODE_OTP;2367 2368done:2369 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",2370 ath10k_cal_mode_str(ar->cal_mode));2371 return 0;2372}2373 2374static void ath10k_core_fetch_btcoex_dt(struct ath10k *ar)2375{2376 struct device_node *node;2377 u8 coex_support = 0;2378 int ret;2379 2380 node = ar->dev->of_node;2381 if (!node)2382 goto out;2383 2384 ret = of_property_read_u8(node, "qcom,coexist-support", &coex_support);2385 if (ret) {2386 ar->coex_support = true;2387 goto out;2388 }2389 2390 if (coex_support) {2391 ar->coex_support = true;2392 } else {2393 ar->coex_support = false;2394 ar->coex_gpio_pin = -1;2395 goto out;2396 }2397 2398 ret = of_property_read_u32(node, "qcom,coexist-gpio-pin",2399 &ar->coex_gpio_pin);2400 if (ret)2401 ar->coex_gpio_pin = -1;2402 2403out:2404 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot coex_support %d coex_gpio_pin %d\n",2405 ar->coex_support, ar->coex_gpio_pin);2406}2407 2408static int ath10k_init_uart(struct ath10k *ar)2409{2410 int ret;2411 2412 /*2413 * Explicitly setting UART prints to zero as target turns it on2414 * based on scratch registers.2415 */2416 ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);2417 if (ret) {2418 ath10k_warn(ar, "could not disable UART prints (%d)\n", ret);2419 return ret;2420 }2421 2422 if (!uart_print) {2423 if (ar->hw_params.uart_pin_workaround) {2424 ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin,2425 ar->hw_params.uart_pin);2426 if (ret) {2427 ath10k_warn(ar, "failed to set UART TX pin: %d",2428 ret);2429 return ret;2430 }2431 }2432 2433 return 0;2434 }2435 2436 ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);2437 if (ret) {2438 ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);2439 return ret;2440 }2441 2442 ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);2443 if (ret) {2444 ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);2445 return ret;2446 }2447 2448 /* Set the UART baud rate to 19200. */2449 ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200);2450 if (ret) {2451 ath10k_warn(ar, "could not set the baud rate (%d)\n", ret);2452 return ret;2453 }2454 2455 ath10k_info(ar, "UART prints enabled\n");2456 return 0;2457}2458 2459static int ath10k_init_hw_params(struct ath10k *ar)2460{2461 const struct ath10k_hw_params *hw_params;2462 int i;2463 2464 for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {2465 hw_params = &ath10k_hw_params_list[i];2466 2467 if (hw_params->bus == ar->hif.bus &&2468 hw_params->id == ar->target_version &&2469 hw_params->dev_id == ar->dev_id)2470 break;2471 }2472 2473 if (i == ARRAY_SIZE(ath10k_hw_params_list)) {2474 ath10k_err(ar, "Unsupported hardware version: 0x%x\n",2475 ar->target_version);2476 return -EINVAL;2477 }2478 2479 ar->hw_params = *hw_params;2480 2481 ath10k_dbg(ar, ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",2482 ar->hw_params.name, ar->target_version);2483 2484 return 0;2485}2486 2487void ath10k_core_start_recovery(struct ath10k *ar)2488{2489 if (test_and_set_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags)) {2490 ath10k_warn(ar, "already restarting\n");2491 return;2492 }2493 2494 queue_work(ar->workqueue, &ar->restart_work);2495}2496EXPORT_SYMBOL(ath10k_core_start_recovery);2497 2498void ath10k_core_napi_enable(struct ath10k *ar)2499{2500 lockdep_assert_held(&ar->conf_mutex);2501 2502 if (test_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags))2503 return;2504 2505 napi_enable(&ar->napi);2506 set_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags);2507}2508EXPORT_SYMBOL(ath10k_core_napi_enable);2509 2510void ath10k_core_napi_sync_disable(struct ath10k *ar)2511{2512 lockdep_assert_held(&ar->conf_mutex);2513 2514 if (!test_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags))2515 return;2516 2517 napi_synchronize(&ar->napi);2518 napi_disable(&ar->napi);2519 clear_bit(ATH10K_FLAG_NAPI_ENABLED, &ar->dev_flags);2520}2521EXPORT_SYMBOL(ath10k_core_napi_sync_disable);2522 2523static void ath10k_core_restart(struct work_struct *work)2524{2525 struct ath10k *ar = container_of(work, struct ath10k, restart_work);2526 int ret;2527 2528 set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);2529 2530 /* Place a barrier to make sure the compiler doesn't reorder2531 * CRASH_FLUSH and calling other functions.2532 */2533 barrier();2534 2535 ieee80211_stop_queues(ar->hw);2536 ath10k_drain_tx(ar);2537 complete(&ar->scan.started);2538 complete(&ar->scan.completed);2539 complete(&ar->scan.on_channel);2540 complete(&ar->offchan_tx_completed);2541 complete(&ar->install_key_done);2542 complete(&ar->vdev_setup_done);2543 complete(&ar->vdev_delete_done);2544 complete(&ar->thermal.wmi_sync);2545 complete(&ar->bss_survey_done);2546 wake_up(&ar->htt.empty_tx_wq);2547 wake_up(&ar->wmi.tx_credits_wq);2548 wake_up(&ar->peer_mapping_wq);2549 2550 /* TODO: We can have one instance of cancelling coverage_class_work by2551 * moving it to ath10k_halt(), so that both stop() and restart() would2552 * call that but it takes conf_mutex() and if we call cancel_work_sync()2553 * with conf_mutex it will deadlock.2554 */2555 cancel_work_sync(&ar->set_coverage_class_work);2556 2557 mutex_lock(&ar->conf_mutex);2558 2559 switch (ar->state) {2560 case ATH10K_STATE_ON:2561 ar->state = ATH10K_STATE_RESTARTING;2562 ath10k_halt(ar);2563 ath10k_scan_finish(ar);2564 ieee80211_restart_hw(ar->hw);2565 break;2566 case ATH10K_STATE_OFF:2567 /* this can happen if driver is being unloaded2568 * or if the crash happens during FW probing2569 */2570 ath10k_warn(ar, "cannot restart a device that hasn't been started\n");2571 break;2572 case ATH10K_STATE_RESTARTING:2573 /* hw restart might be requested from multiple places */2574 break;2575 case ATH10K_STATE_RESTARTED:2576 ar->state = ATH10K_STATE_WEDGED;2577 fallthrough;2578 case ATH10K_STATE_WEDGED:2579 ath10k_warn(ar, "device is wedged, will not restart\n");2580 break;2581 case ATH10K_STATE_UTF:2582 ath10k_warn(ar, "firmware restart in UTF mode not supported\n");2583 break;2584 }2585 2586 mutex_unlock(&ar->conf_mutex);2587 2588 ret = ath10k_coredump_submit(ar);2589 if (ret)2590 ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d",2591 ret);2592 2593 complete(&ar->driver_recovery);2594}2595 2596static void ath10k_core_set_coverage_class_work(struct work_struct *work)2597{2598 struct ath10k *ar = container_of(work, struct ath10k,2599 set_coverage_class_work);2600 2601 if (ar->hw_params.hw_ops->set_coverage_class)2602 ar->hw_params.hw_ops->set_coverage_class(ar, -1);2603}2604 2605static int ath10k_core_init_firmware_features(struct ath10k *ar)2606{2607 struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;2608 int max_num_peers;2609 2610 if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) &&2611 !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {2612 ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");2613 return -EINVAL;2614 }2615 2616 if (fw_file->wmi_op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {2617 ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",2618 ATH10K_FW_WMI_OP_VERSION_MAX, fw_file->wmi_op_version);2619 return -EINVAL;2620 }2621 2622 ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_NATIVE_WIFI;2623 switch (ath10k_cryptmode_param) {2624 case ATH10K_CRYPT_MODE_HW:2625 clear_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);2626 clear_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);2627 break;2628 case ATH10K_CRYPT_MODE_SW:2629 if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,2630 fw_file->fw_features)) {2631 ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");2632 return -EINVAL;2633 }2634 2635 set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);2636 set_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);2637 break;2638 default:2639 ath10k_info(ar, "invalid cryptmode: %d\n",2640 ath10k_cryptmode_param);2641 return -EINVAL;2642 }2643 2644 ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;2645 ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;2646 2647 if (ath10k_frame_mode == ATH10K_HW_TXRX_RAW) {2648 if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,2649 fw_file->fw_features)) {2650 ath10k_err(ar, "rawmode = 1 requires support from firmware");2651 return -EINVAL;2652 }2653 set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);2654 }2655 2656 if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {2657 ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;2658 2659 /* Workaround:2660 *2661 * Firmware A-MSDU aggregation breaks with RAW Tx encap mode2662 * and causes enormous performance issues (malformed frames,2663 * etc).2664 *2665 * Disabling A-MSDU makes RAW mode stable with heavy traffic2666 * albeit a bit slower compared to regular operation.2667 */2668 ar->htt.max_num_amsdu = 1;2669 }2670 2671 /* Backwards compatibility for firmwares without2672 * ATH10K_FW_IE_WMI_OP_VERSION.2673 */2674 if (fw_file->wmi_op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {2675 if (test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) {2676 if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,2677 fw_file->fw_features))2678 fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_2;2679 else2680 fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_10_1;2681 } else {2682 fw_file->wmi_op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;2683 }2684 }2685 2686 switch (fw_file->wmi_op_version) {2687 case ATH10K_FW_WMI_OP_VERSION_MAIN:2688 max_num_peers = TARGET_NUM_PEERS;2689 ar->max_num_stations = TARGET_NUM_STATIONS;2690 ar->max_num_vdevs = TARGET_NUM_VDEVS;2691 ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;2692 ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |2693 WMI_STAT_PEER;2694 ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;2695 break;2696 case ATH10K_FW_WMI_OP_VERSION_10_1:2697 case ATH10K_FW_WMI_OP_VERSION_10_2:2698 case ATH10K_FW_WMI_OP_VERSION_10_2_4:2699 if (ath10k_peer_stats_enabled(ar)) {2700 max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;2701 ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;2702 } else {2703 max_num_peers = TARGET_10X_NUM_PEERS;2704 ar->max_num_stations = TARGET_10X_NUM_STATIONS;2705 }2706 ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;2707 ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;2708 ar->fw_stats_req_mask = WMI_STAT_PEER;2709 ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;2710 break;2711 case ATH10K_FW_WMI_OP_VERSION_TLV:2712 max_num_peers = TARGET_TLV_NUM_PEERS;2713 ar->max_num_stations = TARGET_TLV_NUM_STATIONS;2714 ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;2715 ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;2716 if (ar->hif.bus == ATH10K_BUS_SDIO)2717 ar->htt.max_num_pending_tx =2718 TARGET_TLV_NUM_MSDU_DESC_HL;2719 else2720 ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;2721 ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;2722 ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV |2723 WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD;2724 ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;2725 ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC;2726 break;2727 case ATH10K_FW_WMI_OP_VERSION_10_4:2728 max_num_peers = TARGET_10_4_NUM_PEERS;2729 ar->max_num_stations = TARGET_10_4_NUM_STATIONS;2730 ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;2731 ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;2732 ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;2733 ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |2734 WMI_10_4_STAT_PEER_EXTD |2735 WMI_10_4_STAT_VDEV_EXTD;2736 ar->max_spatial_stream = ar->hw_params.max_spatial_stream;2737 ar->max_num_tdls_vdevs = TARGET_10_4_NUM_TDLS_VDEVS;2738 2739 if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,2740 fw_file->fw_features))2741 ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC;2742 else2743 ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;2744 break;2745 case ATH10K_FW_WMI_OP_VERSION_UNSET:2746 case ATH10K_FW_WMI_OP_VERSION_MAX:2747 default:2748 WARN_ON(1);2749 return -EINVAL;2750 }2751 2752 if (ar->hw_params.num_peers)2753 ar->max_num_peers = ar->hw_params.num_peers;2754 else2755 ar->max_num_peers = max_num_peers;2756 2757 /* Backwards compatibility for firmwares without2758 * ATH10K_FW_IE_HTT_OP_VERSION.2759 */2760 if (fw_file->htt_op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) {2761 switch (fw_file->wmi_op_version) {2762 case ATH10K_FW_WMI_OP_VERSION_MAIN:2763 fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_MAIN;2764 break;2765 case ATH10K_FW_WMI_OP_VERSION_10_1:2766 case ATH10K_FW_WMI_OP_VERSION_10_2:2767 case ATH10K_FW_WMI_OP_VERSION_10_2_4:2768 fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_10_1;2769 break;2770 case ATH10K_FW_WMI_OP_VERSION_TLV:2771 fw_file->htt_op_version = ATH10K_FW_HTT_OP_VERSION_TLV;2772 break;2773 case ATH10K_FW_WMI_OP_VERSION_10_4:2774 case ATH10K_FW_WMI_OP_VERSION_UNSET:2775 case ATH10K_FW_WMI_OP_VERSION_MAX:2776 ath10k_err(ar, "htt op version not found from fw meta data");2777 return -EINVAL;2778 }2779 }2780 2781 return 0;2782}2783 2784static int ath10k_core_reset_rx_filter(struct ath10k *ar)2785{2786 int ret;2787 int vdev_id;2788 int vdev_type;2789 int vdev_subtype;2790 const u8 *vdev_addr;2791 2792 vdev_id = 0;2793 vdev_type = WMI_VDEV_TYPE_STA;2794 vdev_subtype = ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE);2795 vdev_addr = ar->mac_addr;2796 2797 ret = ath10k_wmi_vdev_create(ar, vdev_id, vdev_type, vdev_subtype,2798 vdev_addr);2799 if (ret) {2800 ath10k_err(ar, "failed to create dummy vdev: %d\n", ret);2801 return ret;2802 }2803 2804 ret = ath10k_wmi_vdev_delete(ar, vdev_id);2805 if (ret) {2806 ath10k_err(ar, "failed to delete dummy vdev: %d\n", ret);2807 return ret;2808 }2809 2810 /* WMI and HTT may use separate HIF pipes and are not guaranteed to be2811 * serialized properly implicitly.2812 *2813 * Moreover (most) WMI commands have no explicit acknowledges. It is2814 * possible to infer it implicitly by poking firmware with echo2815 * command - getting a reply means all preceding comments have been2816 * (mostly) processed.2817 *2818 * In case of vdev create/delete this is sufficient.2819 *2820 * Without this it's possible to end up with a race when HTT Rx ring is2821 * started before vdev create/delete hack is complete allowing a short2822 * window of opportunity to receive (and Tx ACK) a bunch of frames.2823 */2824 ret = ath10k_wmi_barrier(ar);2825 if (ret) {2826 ath10k_err(ar, "failed to ping firmware: %d\n", ret);2827 return ret;2828 }2829 2830 return 0;2831}2832 2833static int ath10k_core_compat_services(struct ath10k *ar)2834{2835 struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file;2836 2837 /* all 10.x firmware versions support thermal throttling but don't2838 * advertise the support via service flags so we have to hardcode2839 * it here2840 */2841 switch (fw_file->wmi_op_version) {2842 case ATH10K_FW_WMI_OP_VERSION_10_1:2843 case ATH10K_FW_WMI_OP_VERSION_10_2:2844 case ATH10K_FW_WMI_OP_VERSION_10_2_4:2845 case ATH10K_FW_WMI_OP_VERSION_10_4:2846 set_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map);2847 break;2848 default:2849 break;2850 }2851 2852 return 0;2853}2854 2855#define TGT_IRAM_READ_PER_ITR (8 * 1024)2856 2857static int ath10k_core_copy_target_iram(struct ath10k *ar)2858{2859 const struct ath10k_hw_mem_layout *hw_mem;2860 const struct ath10k_mem_region *tmp, *mem_region = NULL;2861 dma_addr_t paddr;2862 void *vaddr = NULL;2863 u8 num_read_itr;2864 int i, ret;2865 u32 len, remaining_len;2866 2867 /* copy target iram feature must work also when2868 * ATH10K_FW_CRASH_DUMP_RAM_DATA is disabled, so2869 * _ath10k_coredump_get_mem_layout() to accomplist that2870 */2871 hw_mem = _ath10k_coredump_get_mem_layout(ar);2872 if (!hw_mem)2873 /* if CONFIG_DEV_COREDUMP is disabled we get NULL, then2874 * just silently disable the feature by doing nothing2875 */2876 return 0;2877 2878 for (i = 0; i < hw_mem->region_table.size; i++) {2879 tmp = &hw_mem->region_table.regions[i];2880 if (tmp->type == ATH10K_MEM_REGION_TYPE_REG) {2881 mem_region = tmp;2882 break;2883 }2884 }2885 2886 if (!mem_region)2887 return -ENOMEM;2888 2889 for (i = 0; i < ar->wmi.num_mem_chunks; i++) {2890 if (ar->wmi.mem_chunks[i].req_id ==2891 WMI_IRAM_RECOVERY_HOST_MEM_REQ_ID) {2892 vaddr = ar->wmi.mem_chunks[i].vaddr;2893 len = ar->wmi.mem_chunks[i].len;2894 break;2895 }2896 }2897 2898 if (!vaddr || !len) {2899 ath10k_warn(ar, "No allocated memory for IRAM back up");2900 return -ENOMEM;2901 }2902 2903 len = (len < mem_region->len) ? len : mem_region->len;2904 paddr = mem_region->start;2905 num_read_itr = len / TGT_IRAM_READ_PER_ITR;2906 remaining_len = len % TGT_IRAM_READ_PER_ITR;2907 for (i = 0; i < num_read_itr; i++) {2908 ret = ath10k_hif_diag_read(ar, paddr, vaddr,2909 TGT_IRAM_READ_PER_ITR);2910 if (ret) {2911 ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",2912 ret);2913 return ret;2914 }2915 2916 paddr += TGT_IRAM_READ_PER_ITR;2917 vaddr += TGT_IRAM_READ_PER_ITR;2918 }2919 2920 if (remaining_len) {2921 ret = ath10k_hif_diag_read(ar, paddr, vaddr, remaining_len);2922 if (ret) {2923 ath10k_warn(ar, "failed to copy firmware IRAM contents: %d",2924 ret);2925 return ret;2926 }2927 }2928 2929 ath10k_dbg(ar, ATH10K_DBG_BOOT, "target IRAM back up completed\n");2930 2931 return 0;2932}2933 2934int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,2935 const struct ath10k_fw_components *fw)2936{2937 int status;2938 u32 val;2939 2940 lockdep_assert_held(&ar->conf_mutex);2941 2942 clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);2943 2944 ar->running_fw = fw;2945 2946 if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,2947 ar->running_fw->fw_file.fw_features)) {2948 ath10k_bmi_start(ar);2949 2950 /* Enable hardware clock to speed up firmware download */2951 if (ar->hw_params.hw_ops->enable_pll_clk) {2952 status = ar->hw_params.hw_ops->enable_pll_clk(ar);2953 ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot enable pll ret %d\n",2954 status);2955 }2956 2957 if (ath10k_init_configure_target(ar)) {2958 status = -EINVAL;2959 goto err;2960 }2961 2962 status = ath10k_download_cal_data(ar);2963 if (status)2964 goto err;2965 2966 /* Some of qca988x solutions are having global reset issue2967 * during target initialization. Bypassing PLL setting before2968 * downloading firmware and letting the SoC run on REF_CLK is2969 * fixing the problem. Corresponding firmware change is also2970 * needed to set the clock source once the target is2971 * initialized.2972 */2973 if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,2974 ar->running_fw->fw_file.fw_features)) {2975 status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1);2976 if (status) {2977 ath10k_err(ar, "could not write to skip_clock_init: %d\n",2978 status);2979 goto err;2980 }2981 }2982 2983 status = ath10k_download_fw(ar);2984 if (status)2985 goto err;2986 2987 status = ath10k_init_uart(ar);2988 if (status)2989 goto err;2990 2991 if (ar->hif.bus == ATH10K_BUS_SDIO) {2992 status = ath10k_init_sdio(ar, mode);2993 if (status) {2994 ath10k_err(ar, "failed to init SDIO: %d\n", status);2995 goto err;2996 }2997 }2998 }2999 3000 ar->htc.htc_ops.target_send_suspend_complete =3001 ath10k_send_suspend_complete;3002 3003 status = ath10k_htc_init(ar);3004 if (status) {3005 ath10k_err(ar, "could not init HTC (%d)\n", status);3006 goto err;3007 }3008 3009 if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,3010 ar->running_fw->fw_file.fw_features)) {3011 status = ath10k_bmi_done(ar);3012 if (status)3013 goto err;3014 }3015 3016 status = ath10k_wmi_attach(ar);3017 if (status) {3018 ath10k_err(ar, "WMI attach failed: %d\n", status);3019 goto err;3020 }3021 3022 status = ath10k_htt_init(ar);3023 if (status) {3024 ath10k_err(ar, "failed to init htt: %d\n", status);3025 goto err_wmi_detach;3026 }3027 3028 status = ath10k_htt_tx_start(&ar->htt);3029 if (status) {3030 ath10k_err(ar, "failed to alloc htt tx: %d\n", status);3031 goto err_wmi_detach;3032 }3033 3034 /* If firmware indicates Full Rx Reorder support it must be used in a3035 * slightly different manner. Let HTT code know.3036 */3037 ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,3038 ar->wmi.svc_map));3039 3040 status = ath10k_htt_rx_alloc(&ar->htt);3041 if (status) {3042 ath10k_err(ar, "failed to alloc htt rx: %d\n", status);3043 goto err_htt_tx_detach;3044 }3045 3046 status = ath10k_hif_start(ar);3047 if (status) {3048 ath10k_err(ar, "could not start HIF: %d\n", status);3049 goto err_htt_rx_detach;3050 }3051 3052 status = ath10k_htc_wait_target(&ar->htc);3053 if (status) {3054 ath10k_err(ar, "failed to connect to HTC: %d\n", status);3055 goto err_hif_stop;3056 }3057 3058 status = ath10k_hif_start_post(ar);3059 if (status) {3060 ath10k_err(ar, "failed to swap mailbox: %d\n", status);3061 goto err_hif_stop;3062 }3063 3064 if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {3065 status = ath10k_htt_connect(&ar->htt);3066 if (status) {3067 ath10k_err(ar, "failed to connect htt (%d)\n", status);3068 goto err_hif_stop;3069 }3070 }3071 3072 status = ath10k_wmi_connect(ar);3073 if (status) {3074 ath10k_err(ar, "could not connect wmi: %d\n", status);3075 goto err_hif_stop;3076 }3077 3078 status = ath10k_htc_start(&ar->htc);3079 if (status) {3080 ath10k_err(ar, "failed to start htc: %d\n", status);3081 goto err_hif_stop;3082 }3083 3084 if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {3085 status = ath10k_wmi_wait_for_service_ready(ar);3086 if (status) {3087 ath10k_warn(ar, "wmi service ready event not received");3088 goto err_hif_stop;3089 }3090 }3091 3092 ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",3093 ar->hw->wiphy->fw_version);3094 3095 if (test_bit(ATH10K_FW_FEATURE_IRAM_RECOVERY,3096 ar->running_fw->fw_file.fw_features)) {3097 status = ath10k_core_copy_target_iram(ar);3098 if (status) {3099 ath10k_warn(ar, "failed to copy target iram contents: %d",3100 status);3101 goto err_hif_stop;3102 }3103 }3104 3105 if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&3106 mode == ATH10K_FIRMWARE_MODE_NORMAL) {3107 val = 0;3108 if (ath10k_peer_stats_enabled(ar))3109 val = WMI_10_4_PEER_STATS;3110 3111 /* Enable vdev stats by default */3112 val |= WMI_10_4_VDEV_STATS;3113 3114 if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))3115 val |= WMI_10_4_BSS_CHANNEL_INFO_64;3116 3117 ath10k_core_fetch_btcoex_dt(ar);3118 3119 /* 10.4 firmware supports BT-Coex without reloading firmware3120 * via pdev param. To support Bluetooth coexistence pdev param,3121 * WMI_COEX_GPIO_SUPPORT of extended resource config should be3122 * enabled always.3123 *3124 * We can still enable BTCOEX if firmware has the support3125 * even though btceox_support value is3126 * ATH10K_DT_BTCOEX_NOT_FOUND3127 */3128 3129 if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) &&3130 test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,3131 ar->running_fw->fw_file.fw_features) &&3132 ar->coex_support)3133 val |= WMI_10_4_COEX_GPIO_SUPPORT;3134 3135 if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,3136 ar->wmi.svc_map))3137 val |= WMI_10_4_TDLS_EXPLICIT_MODE_ONLY;3138 3139 if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA,3140 ar->wmi.svc_map))3141 val |= WMI_10_4_TDLS_UAPSD_BUFFER_STA;3142 3143 if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI,3144 ar->wmi.svc_map))3145 val |= WMI_10_4_TX_DATA_ACK_RSSI;3146 3147 if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))3148 val |= WMI_10_4_REPORT_AIRTIME;3149 3150 if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,3151 ar->wmi.svc_map))3152 val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT;3153 3154 status = ath10k_mac_ext_resource_config(ar, val);3155 if (status) {3156 ath10k_err(ar,3157 "failed to send ext resource cfg command : %d\n",3158 status);3159 goto err_hif_stop;3160 }3161 }3162 3163 status = ath10k_wmi_cmd_init(ar);3164 if (status) {3165 ath10k_err(ar, "could not send WMI init command (%d)\n",3166 status);3167 goto err_hif_stop;3168 }3169 3170 status = ath10k_wmi_wait_for_unified_ready(ar);3171 if (status) {3172 ath10k_err(ar, "wmi unified ready event not received\n");3173 goto err_hif_stop;3174 }3175 3176 status = ath10k_core_compat_services(ar);3177 if (status) {3178 ath10k_err(ar, "compat services failed: %d\n", status);3179 goto err_hif_stop;3180 }3181 3182 status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr);3183 if (status && status != -EOPNOTSUPP) {3184 ath10k_err(ar,3185 "failed to set base mac address: %d\n", status);3186 goto err_hif_stop;3187 }3188 3189 /* Some firmware revisions do not properly set up hardware rx filter3190 * registers.3191 *3192 * A known example from QCA9880 and 10.2.4 is that MAC_PCU_ADDR1_MASK3193 * is filled with 0s instead of 1s allowing HW to respond with ACKs to3194 * any frames that matches MAC_PCU_RX_FILTER which is also3195 * misconfigured to accept anything.3196 *3197 * The ADDR1 is programmed using internal firmware structure field and3198 * can't be (easily/sanely) reached from the driver explicitly. It is3199 * possible to implicitly make it correct by creating a dummy vdev and3200 * then deleting it.3201 */3202 if (ar->hw_params.hw_filter_reset_required &&3203 mode == ATH10K_FIRMWARE_MODE_NORMAL) {3204 status = ath10k_core_reset_rx_filter(ar);3205 if (status) {3206 ath10k_err(ar,3207 "failed to reset rx filter: %d\n", status);3208 goto err_hif_stop;3209 }3210 }3211 3212 status = ath10k_htt_rx_ring_refill(ar);3213 if (status) {3214 ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);3215 goto err_hif_stop;3216 }3217 3218 if (ar->max_num_vdevs >= 64)3219 ar->free_vdev_map = 0xFFFFFFFFFFFFFFFFLL;3220 else3221 ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;3222 3223 INIT_LIST_HEAD(&ar->arvifs);3224 3225 /* we don't care about HTT in UTF mode */3226 if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {3227 status = ath10k_htt_setup(&ar->htt);3228 if (status) {3229 ath10k_err(ar, "failed to setup htt: %d\n", status);3230 goto err_hif_stop;3231 }3232 }3233 3234 status = ath10k_debug_start(ar);3235 if (status)3236 goto err_hif_stop;3237 3238 status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);3239 if (status && status != -EOPNOTSUPP) {3240 ath10k_warn(ar, "set target log mode failed: %d\n", status);3241 goto err_hif_stop;3242 }3243 3244 status = ath10k_leds_start(ar);3245 if (status)3246 goto err_hif_stop;3247 3248 return 0;3249 3250err_hif_stop:3251 ath10k_hif_stop(ar);3252err_htt_rx_detach:3253 ath10k_htt_rx_free(&ar->htt);3254err_htt_tx_detach:3255 ath10k_htt_tx_free(&ar->htt);3256err_wmi_detach:3257 ath10k_wmi_detach(ar);3258err:3259 return status;3260}3261EXPORT_SYMBOL(ath10k_core_start);3262 3263int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)3264{3265 int ret;3266 unsigned long time_left;3267 3268 reinit_completion(&ar->target_suspend);3269 3270 ret = ath10k_wmi_pdev_suspend_target(ar, suspend_opt);3271 if (ret) {3272 ath10k_warn(ar, "could not suspend target (%d)\n", ret);3273 return ret;3274 }3275 3276 time_left = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);3277 3278 if (!time_left) {3279 ath10k_warn(ar, "suspend timed out - target pause event never came\n");3280 return -ETIMEDOUT;3281 }3282 3283 return 0;3284}3285 3286void ath10k_core_stop(struct ath10k *ar)3287{3288 lockdep_assert_held(&ar->conf_mutex);3289 ath10k_debug_stop(ar);3290 3291 /* try to suspend target */3292 if (ar->state != ATH10K_STATE_RESTARTING &&3293 ar->state != ATH10K_STATE_UTF)3294 ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);3295 3296 ath10k_hif_stop(ar);3297 ath10k_htt_tx_stop(&ar->htt);3298 ath10k_htt_rx_free(&ar->htt);3299 ath10k_wmi_detach(ar);3300 3301 ar->id.bmi_ids_valid = false;3302}3303EXPORT_SYMBOL(ath10k_core_stop);3304 3305/* mac80211 manages fw/hw initialization through start/stop hooks. However in3306 * order to know what hw capabilities should be advertised to mac80211 it is3307 * necessary to load the firmware (and tear it down immediately since start3308 * hook will try to init it again) before registering3309 */3310static int ath10k_core_probe_fw(struct ath10k *ar)3311{3312 struct bmi_target_info target_info;3313 int ret = 0;3314 3315 ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);3316 if (ret) {3317 ath10k_err(ar, "could not power on hif bus (%d)\n", ret);3318 return ret;3319 }3320 3321 switch (ar->hif.bus) {3322 case ATH10K_BUS_SDIO:3323 memset(&target_info, 0, sizeof(target_info));3324 ret = ath10k_bmi_get_target_info_sdio(ar, &target_info);3325 if (ret) {3326 ath10k_err(ar, "could not get target info (%d)\n", ret);3327 goto err_power_down;3328 }3329 ar->target_version = target_info.version;3330 ar->hw->wiphy->hw_version = target_info.version;3331 break;3332 case ATH10K_BUS_PCI:3333 case ATH10K_BUS_AHB:3334 case ATH10K_BUS_USB:3335 memset(&target_info, 0, sizeof(target_info));3336 ret = ath10k_bmi_get_target_info(ar, &target_info);3337 if (ret) {3338 ath10k_err(ar, "could not get target info (%d)\n", ret);3339 goto err_power_down;3340 }3341 ar->target_version = target_info.version;3342 ar->hw->wiphy->hw_version = target_info.version;3343 break;3344 case ATH10K_BUS_SNOC:3345 memset(&target_info, 0, sizeof(target_info));3346 ret = ath10k_hif_get_target_info(ar, &target_info);3347 if (ret) {3348 ath10k_err(ar, "could not get target info (%d)\n", ret);3349 goto err_power_down;3350 }3351 ar->target_version = target_info.version;3352 ar->hw->wiphy->hw_version = target_info.version;3353 break;3354 default:3355 ath10k_err(ar, "incorrect hif bus type: %d\n", ar->hif.bus);3356 }3357 3358 ret = ath10k_init_hw_params(ar);3359 if (ret) {3360 ath10k_err(ar, "could not get hw params (%d)\n", ret);3361 goto err_power_down;3362 }3363 3364 ret = ath10k_core_fetch_firmware_files(ar);3365 if (ret) {3366 ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);3367 goto err_power_down;3368 }3369 3370 BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) !=3371 sizeof(ar->normal_mode_fw.fw_file.fw_version));3372 memcpy(ar->hw->wiphy->fw_version, ar->normal_mode_fw.fw_file.fw_version,3373 sizeof(ar->hw->wiphy->fw_version));3374 3375 ath10k_debug_print_hwfw_info(ar);3376 3377 if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,3378 ar->normal_mode_fw.fw_file.fw_features)) {3379 ret = ath10k_core_pre_cal_download(ar);3380 if (ret) {3381 /* pre calibration data download is not necessary3382 * for all the chipsets. Ignore failures and continue.3383 */3384 ath10k_dbg(ar, ATH10K_DBG_BOOT,3385 "could not load pre cal data: %d\n", ret);3386 }3387 3388 ret = ath10k_core_get_board_id_from_otp(ar);3389 if (ret && ret != -EOPNOTSUPP) {3390 ath10k_err(ar, "failed to get board id from otp: %d\n",3391 ret);3392 goto err_free_firmware_files;3393 }3394 3395 ret = ath10k_core_check_smbios(ar);3396 if (ret)3397 ath10k_dbg(ar, ATH10K_DBG_BOOT, "SMBIOS bdf variant name not set.\n");3398 3399 ret = ath10k_core_check_dt(ar);3400 if (ret)3401 ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");3402 3403 ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD);3404 if (ret) {3405 ath10k_err(ar, "failed to fetch board file: %d\n", ret);3406 goto err_free_firmware_files;3407 }3408 3409 ath10k_debug_print_board_info(ar);3410 }3411 3412 device_get_mac_address(ar->dev, ar->mac_addr);3413 3414 ret = ath10k_core_init_firmware_features(ar);3415 if (ret) {3416 ath10k_err(ar, "fatal problem with firmware features: %d\n",3417 ret);3418 goto err_free_firmware_files;3419 }3420 3421 if (!test_bit(ATH10K_FW_FEATURE_NON_BMI,3422 ar->normal_mode_fw.fw_file.fw_features)) {3423 ret = ath10k_swap_code_seg_init(ar,3424 &ar->normal_mode_fw.fw_file);3425 if (ret) {3426 ath10k_err(ar, "failed to initialize code swap segment: %d\n",3427 ret);3428 goto err_free_firmware_files;3429 }3430 }3431 3432 mutex_lock(&ar->conf_mutex);3433 3434 ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL,3435 &ar->normal_mode_fw);3436 if (ret) {3437 ath10k_err(ar, "could not init core (%d)\n", ret);3438 goto err_unlock;3439 }3440 3441 ath10k_debug_print_boot_info(ar);3442 ath10k_core_stop(ar);3443 3444 mutex_unlock(&ar->conf_mutex);3445 3446 ath10k_hif_power_down(ar);3447 return 0;3448 3449err_unlock:3450 mutex_unlock(&ar->conf_mutex);3451 3452err_free_firmware_files:3453 ath10k_core_free_firmware_files(ar);3454 3455err_power_down:3456 ath10k_hif_power_down(ar);3457 3458 return ret;3459}3460 3461static void ath10k_core_register_work(struct work_struct *work)3462{3463 struct ath10k *ar = container_of(work, struct ath10k, register_work);3464 int status;3465 3466 /* peer stats are enabled by default */3467 set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);3468 3469 status = ath10k_core_probe_fw(ar);3470 if (status) {3471 ath10k_err(ar, "could not probe fw (%d)\n", status);3472 goto err;3473 }3474 3475 status = ath10k_mac_register(ar);3476 if (status) {3477 ath10k_err(ar, "could not register to mac80211 (%d)\n", status);3478 goto err_release_fw;3479 }3480 3481 status = ath10k_coredump_register(ar);3482 if (status) {3483 ath10k_err(ar, "unable to register coredump\n");3484 goto err_unregister_mac;3485 }3486 3487 status = ath10k_debug_register(ar);3488 if (status) {3489 ath10k_err(ar, "unable to initialize debugfs\n");3490 goto err_unregister_coredump;3491 }3492 3493 status = ath10k_spectral_create(ar);3494 if (status) {3495 ath10k_err(ar, "failed to initialize spectral\n");3496 goto err_debug_destroy;3497 }3498 3499 status = ath10k_thermal_register(ar);3500 if (status) {3501 ath10k_err(ar, "could not register thermal device: %d\n",3502 status);3503 goto err_spectral_destroy;3504 }3505 3506 status = ath10k_leds_register(ar);3507 if (status) {3508 ath10k_err(ar, "could not register leds: %d\n",3509 status);3510 goto err_thermal_unregister;3511 }3512 3513 set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);3514 return;3515 3516err_thermal_unregister:3517 ath10k_thermal_unregister(ar);3518err_spectral_destroy:3519 ath10k_spectral_destroy(ar);3520err_debug_destroy:3521 ath10k_debug_destroy(ar);3522err_unregister_coredump:3523 ath10k_coredump_unregister(ar);3524err_unregister_mac:3525 ath10k_mac_unregister(ar);3526err_release_fw:3527 ath10k_core_free_firmware_files(ar);3528err:3529 /* TODO: It's probably a good idea to release device from the driver3530 * but calling device_release_driver() here will cause a deadlock.3531 */3532 return;3533}3534 3535int ath10k_core_register(struct ath10k *ar,3536 const struct ath10k_bus_params *bus_params)3537{3538 ar->bus_param = *bus_params;3539 3540 queue_work(ar->workqueue, &ar->register_work);3541 3542 return 0;3543}3544EXPORT_SYMBOL(ath10k_core_register);3545 3546void ath10k_core_unregister(struct ath10k *ar)3547{3548 cancel_work_sync(&ar->register_work);3549 3550 if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))3551 return;3552 3553 ath10k_leds_unregister(ar);3554 3555 ath10k_thermal_unregister(ar);3556 /* Stop spectral before unregistering from mac80211 to remove the3557 * relayfs debugfs file cleanly. Otherwise the parent debugfs tree3558 * would be already be free'd recursively, leading to a double free.3559 */3560 ath10k_spectral_destroy(ar);3561 3562 /* We must unregister from mac80211 before we stop HTC and HIF.3563 * Otherwise we will fail to submit commands to FW and mac80211 will be3564 * unhappy about callback failures.3565 */3566 ath10k_mac_unregister(ar);3567 3568 ath10k_testmode_destroy(ar);3569 3570 ath10k_core_free_firmware_files(ar);3571 ath10k_core_free_board_files(ar);3572 3573 ath10k_debug_unregister(ar);3574}3575EXPORT_SYMBOL(ath10k_core_unregister);3576 3577struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,3578 enum ath10k_bus bus,3579 enum ath10k_hw_rev hw_rev,3580 const struct ath10k_hif_ops *hif_ops)3581{3582 struct ath10k *ar;3583 int ret;3584 3585 ar = ath10k_mac_create(priv_size);3586 if (!ar)3587 return NULL;3588 3589 ar->ath_common.priv = ar;3590 ar->ath_common.hw = ar->hw;3591 ar->dev = dev;3592 ar->hw_rev = hw_rev;3593 ar->hif.ops = hif_ops;3594 ar->hif.bus = bus;3595 3596 switch (hw_rev) {3597 case ATH10K_HW_QCA988X:3598 case ATH10K_HW_QCA9887:3599 ar->regs = &qca988x_regs;3600 ar->hw_ce_regs = &qcax_ce_regs;3601 ar->hw_values = &qca988x_values;3602 break;3603 case ATH10K_HW_QCA6174:3604 case ATH10K_HW_QCA9377:3605 ar->regs = &qca6174_regs;3606 ar->hw_ce_regs = &qcax_ce_regs;3607 ar->hw_values = &qca6174_values;3608 break;3609 case ATH10K_HW_QCA99X0:3610 case ATH10K_HW_QCA9984:3611 ar->regs = &qca99x0_regs;3612 ar->hw_ce_regs = &qcax_ce_regs;3613 ar->hw_values = &qca99x0_values;3614 break;3615 case ATH10K_HW_QCA9888:3616 ar->regs = &qca99x0_regs;3617 ar->hw_ce_regs = &qcax_ce_regs;3618 ar->hw_values = &qca9888_values;3619 break;3620 case ATH10K_HW_QCA4019:3621 ar->regs = &qca4019_regs;3622 ar->hw_ce_regs = &qcax_ce_regs;3623 ar->hw_values = &qca4019_values;3624 break;3625 case ATH10K_HW_WCN3990:3626 ar->regs = &wcn3990_regs;3627 ar->hw_ce_regs = &wcn3990_ce_regs;3628 ar->hw_values = &wcn3990_values;3629 break;3630 default:3631 ath10k_err(ar, "unsupported core hardware revision %d\n",3632 hw_rev);3633 ret = -EOPNOTSUPP;3634 goto err_free_mac;3635 }3636 3637 init_completion(&ar->scan.started);3638 init_completion(&ar->scan.completed);3639 init_completion(&ar->scan.on_channel);3640 init_completion(&ar->target_suspend);3641 init_completion(&ar->driver_recovery);3642 init_completion(&ar->wow.wakeup_completed);3643 3644 init_completion(&ar->install_key_done);3645 init_completion(&ar->vdev_setup_done);3646 init_completion(&ar->vdev_delete_done);3647 init_completion(&ar->thermal.wmi_sync);3648 init_completion(&ar->bss_survey_done);3649 init_completion(&ar->peer_delete_done);3650 init_completion(&ar->peer_stats_info_complete);3651 3652 INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);3653 3654 ar->workqueue = create_singlethread_workqueue("ath10k_wq");3655 if (!ar->workqueue)3656 goto err_free_mac;3657 3658 ar->workqueue_aux = create_singlethread_workqueue("ath10k_aux_wq");3659 if (!ar->workqueue_aux)3660 goto err_free_wq;3661 3662 ar->workqueue_tx_complete =3663 create_singlethread_workqueue("ath10k_tx_complete_wq");3664 if (!ar->workqueue_tx_complete)3665 goto err_free_aux_wq;3666 3667 mutex_init(&ar->conf_mutex);3668 mutex_init(&ar->dump_mutex);3669 spin_lock_init(&ar->data_lock);3670 3671 for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++)3672 spin_lock_init(&ar->queue_lock[ac]);3673 3674 INIT_LIST_HEAD(&ar->peers);3675 init_waitqueue_head(&ar->peer_mapping_wq);3676 init_waitqueue_head(&ar->htt.empty_tx_wq);3677 init_waitqueue_head(&ar->wmi.tx_credits_wq);3678 3679 skb_queue_head_init(&ar->htt.rx_indication_head);3680 3681 init_completion(&ar->offchan_tx_completed);3682 INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);3683 skb_queue_head_init(&ar->offchan_tx_queue);3684 3685 INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);3686 skb_queue_head_init(&ar->wmi_mgmt_tx_queue);3687 3688 INIT_WORK(&ar->register_work, ath10k_core_register_work);3689 INIT_WORK(&ar->restart_work, ath10k_core_restart);3690 INIT_WORK(&ar->set_coverage_class_work,3691 ath10k_core_set_coverage_class_work);3692 3693 ar->napi_dev = alloc_netdev_dummy(0);3694 if (!ar->napi_dev)3695 goto err_free_tx_complete;3696 3697 ret = ath10k_coredump_create(ar);3698 if (ret)3699 goto err_free_netdev;3700 3701 ret = ath10k_debug_create(ar);3702 if (ret)3703 goto err_free_coredump;3704 3705 return ar;3706 3707err_free_coredump:3708 ath10k_coredump_destroy(ar);3709err_free_netdev:3710 free_netdev(ar->napi_dev);3711err_free_tx_complete:3712 destroy_workqueue(ar->workqueue_tx_complete);3713err_free_aux_wq:3714 destroy_workqueue(ar->workqueue_aux);3715err_free_wq:3716 destroy_workqueue(ar->workqueue);3717err_free_mac:3718 ath10k_mac_destroy(ar);3719 3720 return NULL;3721}3722EXPORT_SYMBOL(ath10k_core_create);3723 3724void ath10k_core_destroy(struct ath10k *ar)3725{3726 destroy_workqueue(ar->workqueue);3727 3728 destroy_workqueue(ar->workqueue_aux);3729 3730 destroy_workqueue(ar->workqueue_tx_complete);3731 3732 free_netdev(ar->napi_dev);3733 ath10k_debug_destroy(ar);3734 ath10k_coredump_destroy(ar);3735 ath10k_htt_tx_destroy(&ar->htt);3736 ath10k_wmi_free_host_mem(ar);3737 ath10k_mac_destroy(ar);3738}3739EXPORT_SYMBOL(ath10k_core_destroy);3740 3741MODULE_AUTHOR("Qualcomm Atheros");3742MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ac wireless LAN cards.");3743MODULE_LICENSE("Dual BSD/GPL");3744