ath10k: refactor ath10k_init_download_firmware()
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / core.c
index eadb225..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;
@@ -224,6 +225,12 @@ 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) {
@@ -257,21 +264,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
        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(ar, "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;
 }
 
@@ -567,28 +595,16 @@ success:
        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(ar, "failed to download board data: %d\n", ret);
-               return ret;
-       }
-
        ret = ath10k_download_and_run_otp(ar);
        if (ret) {
                ath10k_err(ar, "failed to run otp: %d\n", ret);
                return ret;
        }
 
-       ret = ath10k_download_fw(ar);
-       if (ret) {
-               ath10k_err(ar, "failed to download firmware: %d\n", ret);
-               return ret;
-       }
-
        return ret;
 }
 
@@ -685,12 +701,15 @@ static void ath10k_core_restart(struct work_struct *work)
        case ATH10K_STATE_WEDGED:
                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;
 
@@ -703,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;
 
@@ -760,10 +783,12 @@ int ath10k_core_start(struct ath10k *ar)
                goto err_hif_stop;
        }
 
-       status = ath10k_htt_connect(&ar->htt);
-       if (status) {
-               ath10k_err(ar, "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);
@@ -778,11 +803,13 @@ int ath10k_core_start(struct ath10k *ar)
                goto err_hif_stop;
        }
 
-       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;
+       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(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
@@ -802,10 +829,13 @@ int ath10k_core_start(struct ath10k *ar)
                goto err_hif_stop;
        }
 
-       status = ath10k_htt_setup(&ar->htt);
-       if (status) {
-               ath10k_err(ar, "failed to setup htt: %d\n", status);
-               goto err_hif_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);
@@ -813,9 +843,9 @@ int ath10k_core_start(struct ath10k *ar)
                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);
 
@@ -861,7 +891,8 @@ 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);
@@ -914,7 +945,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        mutex_lock(&ar->conf_mutex);
 
-       ret = ath10k_core_start(ar);
+       ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
        if (ret) {
                ath10k_err(ar, "could not init core (%d)\n", ret);
                ath10k_core_free_firmware_files(ar);
@@ -1041,6 +1072,8 @@ void ath10k_core_unregister(struct ath10k *ar)
         * unhappy about callback failures. */
        ath10k_mac_unregister(ar);
 
+       ath10k_testmode_destroy(ar);
+
        ath10k_core_free_firmware_files(ar);
 
        ath10k_debug_unregister(ar);
@@ -1048,6 +1081,7 @@ void ath10k_core_unregister(struct ath10k *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;
@@ -1064,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);