ath10k: print more driver info when firmware crashes
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / ath10k / core.c
index 82017f56e6613a484b224a2d9d41f8aa796f16c9..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,45 +788,40 @@ 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;
+       else
+               ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
 
-       ar->free_vdev_map = (1 << 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_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:
@@ -858,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);
@@ -976,15 +983,25 @@ 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:
        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;
 }
 
@@ -1013,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. */
@@ -1024,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;
 
@@ -1039,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);
@@ -1050,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)