#include "bmi.h"
#include "debug.h"
#include "htt.h"
+#include "testmode.h"
unsigned int ath10k_debug_mask;
static bool uart_print;
static void ath10k_send_suspend_complete(struct ath10k *ar)
{
- ath10k_dbg(ATH10K_DBG_BOOT, "boot suspend complete\n");
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot suspend complete\n");
complete(&ar->target_suspend);
}
ret = ath10k_bmi_write32(ar, hi_app_host_interest,
HTC_PROTOCOL_VERSION);
if (ret) {
- ath10k_err("settings HTC version failed\n");
+ ath10k_err(ar, "settings HTC version failed\n");
return ret;
}
/* set the firmware mode to STA/IBSS/AP */
ret = ath10k_bmi_read32(ar, hi_option_flag, ¶m_host);
if (ret) {
- ath10k_err("setting firmware mode (1/2) failed\n");
+ ath10k_err(ar, "setting firmware mode (1/2) failed\n");
return ret;
}
ret = ath10k_bmi_write32(ar, hi_option_flag, param_host);
if (ret) {
- ath10k_err("setting firmware mode (2/2) failed\n");
+ ath10k_err(ar, "setting firmware mode (2/2) failed\n");
return ret;
}
/* We do all byte-swapping on the host */
ret = ath10k_bmi_write32(ar, hi_be, 0);
if (ret) {
- ath10k_err("setting host CPU BE mode failed\n");
+ ath10k_err(ar, "setting host CPU BE mode failed\n");
return ret;
}
ret = ath10k_bmi_write32(ar, hi_fw_swap, 0);
if (ret) {
- ath10k_err("setting FW data/desc swap flags failed\n");
+ ath10k_err(ar, "setting FW data/desc swap flags failed\n");
return ret;
}
ret = ath10k_bmi_read32(ar, hi_board_ext_data, &board_ext_data_addr);
if (ret) {
- ath10k_err("could not read board ext data addr (%d)\n", ret);
+ ath10k_err(ar, "could not read board ext data addr (%d)\n",
+ ret);
return ret;
}
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot push board extended data addr 0x%x\n",
board_ext_data_addr);
return 0;
if (ar->board_len != (board_data_size + board_ext_data_size)) {
- ath10k_err("invalid board (ext) data sizes %zu != %d+%d\n",
+ ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
ar->board_len, board_data_size, board_ext_data_size);
return -EINVAL;
}
ar->board_data + board_data_size,
board_ext_data_size);
if (ret) {
- ath10k_err("could not write board ext data (%d)\n", ret);
+ ath10k_err(ar, "could not write board ext data (%d)\n", ret);
return ret;
}
ret = ath10k_bmi_write32(ar, hi_board_ext_data_config,
(board_ext_data_size << 16) | 1);
if (ret) {
- ath10k_err("could not write board ext data bit (%d)\n", ret);
+ ath10k_err(ar, "could not write board ext data bit (%d)\n",
+ ret);
return ret;
}
ret = ath10k_push_board_ext_data(ar);
if (ret) {
- ath10k_err("could not push board ext data (%d)\n", ret);
+ ath10k_err(ar, "could not push board ext data (%d)\n", ret);
goto exit;
}
ret = ath10k_bmi_read32(ar, hi_board_data, &address);
if (ret) {
- ath10k_err("could not read board data addr (%d)\n", ret);
+ ath10k_err(ar, "could not read board data addr (%d)\n", ret);
goto exit;
}
min_t(u32, board_data_size,
ar->board_len));
if (ret) {
- ath10k_err("could not write board data (%d)\n", ret);
+ ath10k_err(ar, "could not write board data (%d)\n", ret);
goto exit;
}
ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
if (ret) {
- ath10k_err("could not write board data bit (%d)\n", ret);
+ ath10k_err(ar, "could not write board data bit (%d)\n", ret);
goto exit;
}
u32 result, address = ar->hw_params.patch_load_addr;
int ret;
+ ret = ath10k_download_board_data(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to download board data: %d\n", ret);
+ return ret;
+ }
+
/* OTP is optional */
if (!ar->otp_data || !ar->otp_len) {
- ath10k_warn("Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
+ ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
ar->otp_data, ar->otp_len);
return 0;
}
- ath10k_dbg(ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
address, ar->otp_len);
ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
if (ret) {
- ath10k_err("could not write otp (%d)\n", ret);
+ ath10k_err(ar, "could not write otp (%d)\n", ret);
return ret;
}
ret = ath10k_bmi_execute(ar, address, 0, &result);
if (ret) {
- ath10k_err("could not execute otp (%d)\n", ret);
+ ath10k_err(ar, "could not execute otp (%d)\n", ret);
return ret;
}
- ath10k_dbg(ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
if (result != 0) {
- ath10k_err("otp calibration failed: %d", result);
+ ath10k_err(ar, "otp calibration failed: %d", result);
return -EINVAL;
}
return 0;
}
-static int ath10k_download_fw(struct ath10k *ar)
+static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
- u32 address;
+ u32 address, data_len;
+ const char *mode_name;
+ const void *data;
int ret;
address = ar->hw_params.patch_load_addr;
- ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
- ar->firmware_len);
+ switch (mode) {
+ case ATH10K_FIRMWARE_MODE_NORMAL:
+ data = ar->firmware_data;
+ data_len = ar->firmware_len;
+ mode_name = "normal";
+ break;
+ case ATH10K_FIRMWARE_MODE_UTF:
+ data = ar->testmode.utf->data;
+ data_len = ar->testmode.utf->size;
+ mode_name = "utf";
+ break;
+ default:
+ ath10k_err(ar, "unknown firmware mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot uploading firmware image %p len %d mode %s\n",
+ data, data_len, mode_name);
+
+ ret = ath10k_bmi_fast_download(ar, address, data, data_len);
if (ret) {
- ath10k_err("could not write fw (%d)\n", ret);
- goto exit;
+ ath10k_err(ar, "failed to download %s firmware: %d\n",
+ mode_name, ret);
+ return ret;
}
-exit:
return ret;
}
int ret = 0;
if (ar->hw_params.fw.fw == NULL) {
- ath10k_err("firmware file not defined\n");
+ ath10k_err(ar, "firmware file not defined\n");
return -EINVAL;
}
if (ar->hw_params.fw.board == NULL) {
- ath10k_err("board data file not defined");
+ ath10k_err(ar, "board data file not defined");
return -EINVAL;
}
ar->hw_params.fw.board);
if (IS_ERR(ar->board)) {
ret = PTR_ERR(ar->board);
- ath10k_err("could not fetch board data (%d)\n", ret);
+ ath10k_err(ar, "could not fetch board data (%d)\n", ret);
goto err;
}
ar->hw_params.fw.fw);
if (IS_ERR(ar->firmware)) {
ret = PTR_ERR(ar->firmware);
- ath10k_err("could not fetch firmware (%d)\n", ret);
+ ath10k_err(ar, "could not fetch firmware (%d)\n", ret);
goto err;
}
ar->hw_params.fw.otp);
if (IS_ERR(ar->otp)) {
ret = PTR_ERR(ar->otp);
- ath10k_err("could not fetch otp (%d)\n", ret);
+ ath10k_err(ar, "could not fetch otp (%d)\n", ret);
goto err;
}
/* first fetch the firmware file (firmware-*.bin) */
ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
if (IS_ERR(ar->firmware)) {
- ath10k_err("could not fetch firmware file '%s/%s': %ld\n",
+ ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware));
return PTR_ERR(ar->firmware);
}
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
if (len < magic_len) {
- ath10k_err("firmware file '%s/%s' too small to contain magic: %zu\n",
+ ath10k_err(ar, "firmware file '%s/%s' too small to contain magic: %zu\n",
ar->hw_params.fw.dir, name, len);
ret = -EINVAL;
goto err;
}
if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
- ath10k_err("invalid firmware magic\n");
+ ath10k_err(ar, "invalid firmware magic\n");
ret = -EINVAL;
goto err;
}
data += sizeof(*hdr);
if (len < ie_len) {
- ath10k_err("invalid length for FW IE %d (%zu < %zu)\n",
+ ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
ie_id, len, ie_len);
ret = -EINVAL;
goto err;
memcpy(ar->hw->wiphy->fw_version, data, ie_len);
ar->hw->wiphy->fw_version[ie_len] = '\0';
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"found fw version %s\n",
ar->hw->wiphy->fw_version);
break;
timestamp = (__le32 *)data;
- ath10k_dbg(ATH10K_DBG_BOOT, "found fw timestamp %d\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw timestamp %d\n",
le32_to_cpup(timestamp));
break;
case ATH10K_FW_IE_FEATURES:
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"found firmware features ie (%zd B)\n",
ie_len);
break;
if (data[index] & (1 << bit)) {
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"Enabling feature bit: %i\n",
i);
__set_bit(i, ar->fw_features);
}
}
- ath10k_dbg_dump(ATH10K_DBG_BOOT, "features", "",
+ ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "",
ar->fw_features,
sizeof(ar->fw_features));
break;
case ATH10K_FW_IE_FW_IMAGE:
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"found fw image ie (%zd B)\n",
ie_len);
break;
case ATH10K_FW_IE_OTP_IMAGE:
- ath10k_dbg(ATH10K_DBG_BOOT,
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
"found otp image ie (%zd B)\n",
ie_len);
break;
default:
- ath10k_warn("Unknown FW IE: %u\n",
+ ath10k_warn(ar, "Unknown FW IE: %u\n",
le32_to_cpu(hdr->id));
break;
}
}
if (!ar->firmware_data || !ar->firmware_len) {
- ath10k_warn("No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
+ ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
ar->hw_params.fw.dir, name);
ret = -ENOMEDIUM;
goto err;
}
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
+ !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+ ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
+ ret = -EINVAL;
+ goto err;
+ }
+
/* now fetch the board file */
if (ar->hw_params.fw.board == NULL) {
- ath10k_err("board data file not defined");
+ ath10k_err(ar, "board data file not defined");
ret = -EINVAL;
goto err;
}
ar->hw_params.fw.board);
if (IS_ERR(ar->board)) {
ret = PTR_ERR(ar->board);
- ath10k_err("could not fetch board data '%s/%s' (%d)\n",
+ ath10k_err(ar, "could not fetch board data '%s/%s' (%d)\n",
ar->hw_params.fw.dir, ar->hw_params.fw.board,
ret);
goto err;
{
int ret;
+ ar->fw_api = 3;
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+
+ ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
+ if (ret == 0)
+ goto success;
+
ar->fw_api = 2;
- ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
if (ret == 0)
goto success;
ar->fw_api = 1;
- ath10k_dbg(ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
ret = ath10k_core_fetch_firmware_api_1(ar);
if (ret)
return ret;
success:
- ath10k_dbg(ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
return 0;
}
-static int ath10k_init_download_firmware(struct ath10k *ar)
+static int ath10k_download_cal_data(struct ath10k *ar)
{
int ret;
- ret = ath10k_download_board_data(ar);
- if (ret) {
- ath10k_err("failed to download board data: %d\n", ret);
- return ret;
- }
-
ret = ath10k_download_and_run_otp(ar);
if (ret) {
- ath10k_err("failed to run otp: %d\n", ret);
- return ret;
- }
-
- ret = ath10k_download_fw(ar);
- if (ret) {
- ath10k_err("failed to download firmware: %d\n", ret);
+ ath10k_err(ar, "failed to run otp: %d\n", ret);
return ret;
}
*/
ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);
if (ret) {
- ath10k_warn("could not disable UART prints (%d)\n", ret);
+ ath10k_warn(ar, "could not disable UART prints (%d)\n", ret);
return ret;
}
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
if (ret) {
- ath10k_warn("could not enable UART prints (%d)\n", ret);
+ ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
return ret;
}
ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);
if (ret) {
- ath10k_warn("could not enable UART prints (%d)\n", ret);
+ ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
return ret;
}
/* Set the UART baud rate to 19200. */
ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200);
if (ret) {
- ath10k_warn("could not set the baud rate (%d)\n", ret);
+ ath10k_warn(ar, "could not set the baud rate (%d)\n", ret);
return ret;
}
- ath10k_info("UART prints enabled\n");
+ ath10k_info(ar, "UART prints enabled\n");
return 0;
}
}
if (i == ARRAY_SIZE(ath10k_hw_params_list)) {
- ath10k_err("Unsupported hardware version: 0x%x\n",
+ ath10k_err(ar, "Unsupported hardware version: 0x%x\n",
ar->target_version);
return -EINVAL;
}
ar->hw_params = *hw_params;
- ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
ar->hw_params.name, ar->target_version);
return 0;
switch (ar->state) {
case ATH10K_STATE_ON:
ar->state = ATH10K_STATE_RESTARTING;
- del_timer_sync(&ar->scan.timeout);
- ath10k_reset_scan((unsigned long)ar);
+ ath10k_hif_stop(ar);
+ ath10k_scan_finish(ar);
ieee80211_restart_hw(ar->hw);
break;
case ATH10K_STATE_OFF:
/* this can happen if driver is being unloaded
* or if the crash happens during FW probing */
- ath10k_warn("cannot restart a device that hasn't been started\n");
+ ath10k_warn(ar, "cannot restart a device that hasn't been started\n");
break;
case ATH10K_STATE_RESTARTING:
/* hw restart might be requested from multiple places */
ar->state = ATH10K_STATE_WEDGED;
/* fall through */
case ATH10K_STATE_WEDGED:
- ath10k_warn("device is wedged, will not restart\n");
+ ath10k_warn(ar, "device is wedged, will not restart\n");
+ break;
+ case ATH10K_STATE_UTF:
+ ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
break;
}
mutex_unlock(&ar->conf_mutex);
}
-int ath10k_core_start(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
int status;
goto err;
}
- status = ath10k_init_download_firmware(ar);
+ status = ath10k_download_cal_data(ar);
+ if (status)
+ goto err;
+
+ status = ath10k_download_fw(ar, mode);
if (status)
goto err;
status = ath10k_htc_init(ar);
if (status) {
- ath10k_err("could not init HTC (%d)\n", status);
+ ath10k_err(ar, "could not init HTC (%d)\n", status);
goto err;
}
status = ath10k_wmi_attach(ar);
if (status) {
- ath10k_err("WMI attach failed: %d\n", status);
+ ath10k_err(ar, "WMI attach failed: %d\n", status);
goto err;
}
status = ath10k_htt_init(ar);
if (status) {
- ath10k_err("failed to init htt: %d\n", status);
+ ath10k_err(ar, "failed to init htt: %d\n", status);
goto err_wmi_detach;
}
status = ath10k_htt_tx_alloc(&ar->htt);
if (status) {
- ath10k_err("failed to alloc htt tx: %d\n", status);
+ ath10k_err(ar, "failed to alloc htt tx: %d\n", status);
goto err_wmi_detach;
}
status = ath10k_htt_rx_alloc(&ar->htt);
if (status) {
- ath10k_err("failed to alloc htt rx: %d\n", status);
+ ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
goto err_htt_tx_detach;
}
status = ath10k_hif_start(ar);
if (status) {
- ath10k_err("could not start HIF: %d\n", status);
+ ath10k_err(ar, "could not start HIF: %d\n", status);
goto err_htt_rx_detach;
}
status = ath10k_htc_wait_target(&ar->htc);
if (status) {
- ath10k_err("failed to connect to HTC: %d\n", status);
+ ath10k_err(ar, "failed to connect to HTC: %d\n", status);
goto err_hif_stop;
}
- status = ath10k_htt_connect(&ar->htt);
- if (status) {
- ath10k_err("failed to connect htt (%d)\n", status);
- goto err_hif_stop;
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_htt_connect(&ar->htt);
+ if (status) {
+ ath10k_err(ar, "failed to connect htt (%d)\n", status);
+ goto err_hif_stop;
+ }
}
status = ath10k_wmi_connect(ar);
if (status) {
- ath10k_err("could not connect wmi: %d\n", status);
+ ath10k_err(ar, "could not connect wmi: %d\n", status);
goto err_hif_stop;
}
status = ath10k_htc_start(&ar->htc);
if (status) {
- ath10k_err("failed to start htc: %d\n", status);
+ ath10k_err(ar, "failed to start htc: %d\n", status);
goto err_hif_stop;
}
- status = ath10k_wmi_wait_for_service_ready(ar);
- if (status <= 0) {
- ath10k_warn("wmi service ready event not received");
- status = -ETIMEDOUT;
- goto err_htc_stop;
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_wmi_wait_for_service_ready(ar);
+ if (status <= 0) {
+ ath10k_warn(ar, "wmi service ready event not received");
+ status = -ETIMEDOUT;
+ goto err_hif_stop;
+ }
}
- ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version);
status = ath10k_wmi_cmd_init(ar);
if (status) {
- ath10k_err("could not send WMI init command (%d)\n", status);
- goto err_htc_stop;
+ ath10k_err(ar, "could not send WMI init command (%d)\n",
+ status);
+ goto err_hif_stop;
}
status = ath10k_wmi_wait_for_unified_ready(ar);
if (status <= 0) {
- ath10k_err("wmi unified ready event not received\n");
+ ath10k_err(ar, "wmi unified ready event not received\n");
status = -ETIMEDOUT;
- goto err_htc_stop;
+ goto err_hif_stop;
}
- status = ath10k_htt_setup(&ar->htt);
- if (status) {
- ath10k_err("failed to setup htt: %d\n", status);
- goto err_htc_stop;
+ /* we don't care about HTT in UTF mode */
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_htt_setup(&ar->htt);
+ if (status) {
+ ath10k_err(ar, "failed to setup htt: %d\n", status);
+ goto err_hif_stop;
+ }
}
status = ath10k_debug_start(ar);
if (status)
- goto err_htc_stop;
+ goto err_hif_stop;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
- ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
+ ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
else
- ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
+ ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs);
- if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
- ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
- ar->hw_params.name,
- ar->target_version,
- ar->chip_id,
- ar->hw->wiphy->fw_version,
- ar->fw_api,
- ar->htt.target_version_major,
- ar->htt.target_version_minor);
-
- __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
-
return 0;
-err_htc_stop:
- ath10k_htc_stop(&ar->htc);
err_hif_stop:
ath10k_hif_stop(ar);
err_htt_rx_detach:
ret = ath10k_wmi_pdev_suspend_target(ar, suspend_opt);
if (ret) {
- ath10k_warn("could not suspend target (%d)\n", ret);
+ ath10k_warn(ar, "could not suspend target (%d)\n", ret);
return ret;
}
ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
if (ret == 0) {
- ath10k_warn("suspend timed out - target pause event never came\n");
+ ath10k_warn(ar, "suspend timed out - target pause event never came\n");
return -ETIMEDOUT;
}
lockdep_assert_held(&ar->conf_mutex);
/* try to suspend target */
- if (ar->state != ATH10K_STATE_RESTARTING)
+ if (ar->state != ATH10K_STATE_RESTARTING &&
+ ar->state != ATH10K_STATE_UTF)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_debug_stop(ar);
- ath10k_htc_stop(&ar->htc);
ath10k_hif_stop(ar);
ath10k_htt_tx_free(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ret = ath10k_hif_power_up(ar);
if (ret) {
- ath10k_err("could not start pci hif (%d)\n", ret);
+ ath10k_err(ar, "could not start pci hif (%d)\n", ret);
return ret;
}
memset(&target_info, 0, sizeof(target_info));
ret = ath10k_bmi_get_target_info(ar, &target_info);
if (ret) {
- ath10k_err("could not get target info (%d)\n", ret);
+ ath10k_err(ar, "could not get target info (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
}
ret = ath10k_init_hw_params(ar);
if (ret) {
- ath10k_err("could not get hw params (%d)\n", ret);
+ ath10k_err(ar, "could not get hw params (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
}
ret = ath10k_core_fetch_firmware_files(ar);
if (ret) {
- ath10k_err("could not fetch firmware files (%d)\n", ret);
+ ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
}
mutex_lock(&ar->conf_mutex);
- ret = ath10k_core_start(ar);
+ ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
- ath10k_err("could not init core (%d)\n", ret);
+ ath10k_err(ar, "could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar);
ath10k_hif_power_down(ar);
mutex_unlock(&ar->conf_mutex);
return ret;
}
+ ath10k_print_driver_info(ar);
ath10k_core_stop(ar);
mutex_unlock(&ar->conf_mutex);
{
u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV);
- ath10k_dbg(ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n",
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n",
ar->chip_id, hw_revision);
/* Check that we are not using hw1.0 (some of them have same pci id
* due to missing hw1.0 workarounds. */
switch (hw_revision) {
case QCA988X_HW_1_0_CHIP_ID_REV:
- ath10k_err("ERROR: qca988x hw1.0 is not supported\n");
+ ath10k_err(ar, "ERROR: qca988x hw1.0 is not supported\n");
return -EOPNOTSUPP;
case QCA988X_HW_2_0_CHIP_ID_REV:
return 0;
default:
- ath10k_warn("Warning: hardware revision unknown (0x%x), expect problems\n",
+ ath10k_warn(ar, "Warning: hardware revision unknown (0x%x), expect problems\n",
ar->chip_id);
return 0;
}
status = ath10k_core_probe_fw(ar);
if (status) {
- ath10k_err("could not probe fw (%d)\n", status);
+ ath10k_err(ar, "could not probe fw (%d)\n", status);
goto err;
}
status = ath10k_mac_register(ar);
if (status) {
- ath10k_err("could not register to mac80211 (%d)\n", status);
+ ath10k_err(ar, "could not register to mac80211 (%d)\n", status);
goto err_release_fw;
}
- status = ath10k_debug_create(ar);
+ status = ath10k_debug_register(ar);
if (status) {
- ath10k_err("unable to initialize debugfs\n");
+ ath10k_err(ar, "unable to initialize debugfs\n");
goto err_unregister_mac;
}
+ status = ath10k_spectral_create(ar);
+ if (status) {
+ ath10k_err(ar, "failed to initialize spectral\n");
+ goto err_debug_destroy;
+ }
+
set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
return;
+err_debug_destroy:
+ ath10k_debug_destroy(ar);
err_unregister_mac:
ath10k_mac_unregister(ar);
err_release_fw:
ath10k_core_free_firmware_files(ar);
err:
- device_release_driver(ar->dev);
+ /* TODO: It's probably a good idea to release device from the driver
+ * but calling device_release_driver() here will cause a deadlock.
+ */
return;
}
status = ath10k_core_check_chip_id(ar);
if (status) {
- ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
+ ath10k_err(ar, "Unsupported chip id 0x%08x\n", ar->chip_id);
return status;
}
if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
return;
+ /* Stop spectral before unregistering from mac80211 to remove the
+ * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
+ * would be already be free'd recursively, leading to a double free.
+ */
+ ath10k_spectral_destroy(ar);
+
/* We must unregister from mac80211 before we stop HTC and HIF.
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
ath10k_mac_unregister(ar);
+ ath10k_testmode_destroy(ar);
+
ath10k_core_free_firmware_files(ar);
- ath10k_debug_destroy(ar);
+ ath10k_debug_unregister(ar);
}
EXPORT_SYMBOL(ath10k_core_unregister);
-struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
+struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
+ enum ath10k_bus bus,
const struct ath10k_hif_ops *hif_ops)
{
struct ath10k *ar;
+ int ret;
- ar = ath10k_mac_create();
+ ar = ath10k_mac_create(priv_size);
if (!ar)
return NULL;
ar->p2p = !!ath10k_p2p;
ar->dev = dev;
- ar->hif.priv = hif_priv;
ar->hif.ops = hif_ops;
+ ar->hif.bus = bus;
init_completion(&ar->scan.started);
init_completion(&ar->scan.completed);
init_completion(&ar->install_key_done);
init_completion(&ar->vdev_setup_done);
- setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
+ INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);
ar->workqueue = create_singlethread_workqueue("ath10k_wq");
if (!ar->workqueue)
- goto err_wq;
+ goto err_free_mac;
mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
INIT_WORK(&ar->register_work, ath10k_core_register_work);
INIT_WORK(&ar->restart_work, ath10k_core_restart);
+ ret = ath10k_debug_create(ar);
+ if (ret)
+ goto err_free_wq;
+
return ar;
-err_wq:
+err_free_wq:
+ destroy_workqueue(ar->workqueue);
+
+err_free_mac:
ath10k_mac_destroy(ar);
+
return NULL;
}
EXPORT_SYMBOL(ath10k_core_create);
flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue);
+ ath10k_debug_destroy(ar);
ath10k_mac_destroy(ar);
}
EXPORT_SYMBOL(ath10k_core_destroy);