ath10k: refactor ath10k_init_download_firmware()
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / core.c
index 7f95bd0..d0b67a7 100644 (file)
@@ -26,6 +26,7 @@
 #include "bmi.h"
 #include "debug.h"
 #include "htt.h"
+#include "testmode.h"
 
 unsigned int ath10k_debug_mask;
 static bool uart_print;
@@ -53,7 +54,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 
 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);
 }
@@ -67,14 +68,14 @@ static int ath10k_init_configure_target(struct ath10k *ar)
        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, &param_host);
        if (ret) {
-               ath10k_err("setting firmware mode (1/2) failed\n");
+               ath10k_err(ar, "setting firmware mode (1/2) failed\n");
                return ret;
        }
 
@@ -93,14 +94,14 @@ static int ath10k_init_configure_target(struct ath10k *ar)
 
        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;
        }
 
@@ -108,7 +109,7 @@ static int ath10k_init_configure_target(struct ath10k *ar)
        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;
        }
 
@@ -146,11 +147,12 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
 
        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);
 
@@ -158,7 +160,7 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
                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;
        }
@@ -167,14 +169,15 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
                                      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;
        }
 
@@ -189,13 +192,13 @@ static int ath10k_download_board_data(struct ath10k *ar)
 
        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;
        }
 
@@ -203,13 +206,13 @@ static int ath10k_download_board_data(struct ath10k *ar)
                                      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;
        }
 
@@ -222,54 +225,81 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
        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;
 }
 
@@ -302,12 +332,12 @@ static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
        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;
        }
 
@@ -316,7 +346,7 @@ static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
                                         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;
        }
 
@@ -328,7 +358,7 @@ static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
                                            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;
        }
 
@@ -344,7 +374,7 @@ static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
                                       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;
        }
 
@@ -369,7 +399,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
        /* 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);
        }
@@ -381,14 +411,14 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
        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;
        }
@@ -410,7 +440,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                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;
@@ -424,7 +454,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                        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;
@@ -434,11 +464,11 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 
                        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);
 
@@ -450,19 +480,19 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                                        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);
 
@@ -471,7 +501,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 
                        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);
 
@@ -480,7 +510,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 
                        break;
                default:
-                       ath10k_warn("Unknown FW IE: %u\n",
+                       ath10k_warn(ar, "Unknown FW IE: %u\n",
                                    le32_to_cpu(hdr->id));
                        break;
                }
@@ -493,7 +523,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
        }
 
        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;
@@ -501,14 +531,14 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
 
        if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
            !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
-               ath10k_err("feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
+               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;
        }
@@ -518,7 +548,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                                         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;
@@ -539,51 +569,39 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
        int ret;
 
        ar->fw_api = 3;
-       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_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;
        }
 
@@ -600,7 +618,7 @@ static int ath10k_init_uart(struct ath10k *ar)
         */
        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;
        }
 
@@ -609,24 +627,24 @@ static int ath10k_init_uart(struct ath10k *ar)
 
        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;
 }
 
@@ -643,14 +661,14 @@ static int ath10k_init_hw_params(struct ath10k *ar)
        }
 
        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;
@@ -665,13 +683,14 @@ static void ath10k_core_restart(struct work_struct *work)
        switch (ar->state) {
        case ATH10K_STATE_ON:
                ar->state = ATH10K_STATE_RESTARTING;
+               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 */
@@ -680,14 +699,17 @@ static void ath10k_core_restart(struct work_struct *work)
                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;
 
@@ -700,7 +722,11 @@ int ath10k_core_start(struct ath10k *ar)
                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;
 
@@ -713,7 +739,7 @@ int ath10k_core_start(struct ath10k *ar)
 
        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;
        }
 
@@ -723,120 +749,108 @@ int ath10k_core_start(struct ath10k *ar)
 
        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);
-               ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
-                           config_enabled(CONFIG_ATH10K_DEBUG),
-                           config_enabled(CONFIG_ATH10K_DEBUGFS),
-                           config_enabled(CONFIG_ATH10K_TRACING),
-                           config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
-       }
-
-       __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:
@@ -858,14 +872,14 @@ int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
 
        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;
        }
 
@@ -877,11 +891,11 @@ void ath10k_core_stop(struct ath10k *ar)
        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);
@@ -900,14 +914,14 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        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;
        }
@@ -917,29 +931,30 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        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);
@@ -952,7 +967,7 @@ static int ath10k_core_check_chip_id(struct ath10k *ar)
 {
        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
@@ -960,7 +975,7 @@ static int ath10k_core_check_chip_id(struct ath10k *ar)
         * 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:
@@ -968,7 +983,7 @@ static int ath10k_core_check_chip_id(struct ath10k *ar)
                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;
        }
@@ -983,25 +998,25 @@ static void ath10k_core_register_work(struct work_struct *work)
 
        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("failed to initialize spectral\n");
+               ath10k_err(ar, "failed to initialize spectral\n");
                goto err_debug_destroy;
        }
 
@@ -1029,7 +1044,7 @@ int ath10k_core_register(struct ath10k *ar, u32 chip_id)
 
        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;
        }
 
@@ -1046,23 +1061,31 @@ void ath10k_core_unregister(struct ath10k *ar)
        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_core_free_firmware_files(ar);
+       ath10k_testmode_destroy(ar);
 
-       ath10k_spectral_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(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(priv_size);
        if (!ar)
@@ -1075,6 +1098,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
        ar->dev = dev;
 
        ar->hif.ops = hif_ops;
+       ar->hif.bus = bus;
 
        init_completion(&ar->scan.started);
        init_completion(&ar->scan.completed);
@@ -1088,7 +1112,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
        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);
@@ -1106,10 +1130,18 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
        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);
@@ -1119,6 +1151,7 @@ void ath10k_core_destroy(struct ath10k *ar)
        flush_workqueue(ar->workqueue);
        destroy_workqueue(ar->workqueue);
 
+       ath10k_debug_destroy(ar);
        ath10k_mac_destroy(ar);
 }
 EXPORT_SYMBOL(ath10k_core_destroy);