ath10k: print more driver info when firmware crashes
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / ath10k / core.c
index 93adb8c5896926c787bb80e6c0869cd7f5fd4672..28f0adea73b63f5cc870c72509f61ddb6f7e2ca3 100644 (file)
@@ -499,6 +499,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                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("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");
@@ -531,6 +538,13 @@ 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);
+
+       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);
 
@@ -651,8 +665,7 @@ static void ath10k_core_restart(struct work_struct *work)
        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_scan_finish(ar);
                ieee80211_restart_hw(ar->hw);
                break;
        case ATH10K_STATE_OFF:
@@ -766,7 +779,7 @@ int ath10k_core_start(struct ath10k *ar)
        if (status <= 0) {
                ath10k_warn("wmi service ready event not received");
                status = -ETIMEDOUT;
-               goto err_htc_stop;
+               goto err_hif_stop;
        }
 
        ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
@@ -775,25 +788,25 @@ int ath10k_core_start(struct ath10k *ar)
        status = ath10k_wmi_cmd_init(ar);
        if (status) {
                ath10k_err("could not send WMI init command (%d)\n", status);
-               goto err_htc_stop;
+               goto err_hif_stop;
        }
 
        status = ath10k_wmi_wait_for_unified_ready(ar);
        if (status <= 0) {
                ath10k_err("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;
+               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;
@@ -802,28 +815,13 @@ int ath10k_core_start(struct ath10k *ar)
 
        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));
-       }
+       if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
+               ath10k_print_driver_info(ar);
 
        __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:
@@ -868,7 +866,6 @@ void ath10k_core_stop(struct ath10k *ar)
                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);
@@ -986,9 +983,17 @@ static void ath10k_core_register_work(struct work_struct *work)
                goto err_unregister_mac;
        }
 
+       status = ath10k_spectral_create(ar);
+       if (status) {
+               ath10k_err("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:
@@ -1025,6 +1030,12 @@ 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. */
@@ -1036,12 +1047,12 @@ void ath10k_core_unregister(struct ath10k *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,
                                  const struct ath10k_hif_ops *hif_ops)
 {
        struct ath10k *ar;
 
-       ar = ath10k_mac_create();
+       ar = ath10k_mac_create(priv_size);
        if (!ar)
                return NULL;
 
@@ -1051,7 +1062,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
        ar->p2p = !!ath10k_p2p;
        ar->dev = dev;
 
-       ar->hif.priv = hif_priv;
        ar->hif.ops = hif_ops;
 
        init_completion(&ar->scan.started);
@@ -1062,7 +1072,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
        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)