ath10k: make core registering async
authorMichal Kazior <michal.kazior@tieto.com>
Fri, 23 May 2014 10:28:47 +0000 (12:28 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 26 May 2014 09:44:44 +0000 (12:44 +0300)
If ath10k was built into the kernel it could stall
booting for 120 seconds by default (60 seconds for
each firmware API variant) waiting for firmware
files before userspace was ready or filesystems
mounted.

Fix this by making the core registering
asynchronous.

This also shoves off about 1 second from boot time
on most systems since the driver is now mostly
initialized in a worker and modprobe takes very
little time to complete.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h

index 3b72f277ef21a95e7e0f416300764eda3c9fb3f2..5980399029b41d40337b41b19a6014e37a69ef0b 100644 (file)
@@ -950,22 +950,15 @@ static int ath10k_core_check_chip_id(struct ath10k *ar)
        return 0;
 }
 
-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+static void ath10k_core_register_work(struct work_struct *work)
 {
+       struct ath10k *ar = container_of(work, struct ath10k, register_work);
        int status;
 
-       ar->chip_id = chip_id;
-
-       status = ath10k_core_check_chip_id(ar);
-       if (status) {
-               ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
-               return status;
-       }
-
        status = ath10k_core_probe_fw(ar);
        if (status) {
                ath10k_err("could not probe fw (%d)\n", status);
-               return status;
+               goto err;
        }
 
        status = ath10k_mac_register(ar);
@@ -980,18 +973,43 @@ int ath10k_core_register(struct ath10k *ar, u32 chip_id)
                goto err_unregister_mac;
        }
 
-       return 0;
+       set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
+       return;
 
 err_unregister_mac:
        ath10k_mac_unregister(ar);
 err_release_fw:
        ath10k_core_free_firmware_files(ar);
-       return status;
+err:
+       device_release_driver(ar->dev);
+       return;
+}
+
+int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+{
+       int status;
+
+       ar->chip_id = chip_id;
+
+       status = ath10k_core_check_chip_id(ar);
+       if (status) {
+               ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
+               return status;
+       }
+
+       queue_work(ar->workqueue, &ar->register_work);
+
+       return 0;
 }
 EXPORT_SYMBOL(ath10k_core_register);
 
 void ath10k_core_unregister(struct ath10k *ar)
 {
+       cancel_work_sync(&ar->register_work);
+
+       if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
+               return;
+
        /* 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. */
@@ -1048,6 +1066,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
        INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
        skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
 
+       INIT_WORK(&ar->register_work, ath10k_core_register_work);
        INIT_WORK(&ar->restart_work, ath10k_core_restart);
 
        return ar;
index 679b2a32331b7c2fccdedce2921af2c09ab918fc..68ceef61933db6b769122ab2500fa524619ac465 100644 (file)
@@ -335,6 +335,7 @@ enum ath10k_dev_flags {
        /* Indicates that ath10k device is during CAC phase of DFS */
        ATH10K_CAC_RUNNING,
        ATH10K_FLAG_FIRST_BOOT_DONE,
+       ATH10K_FLAG_CORE_REGISTERED,
 };
 
 struct ath10k {
@@ -476,6 +477,7 @@ struct ath10k {
 
        enum ath10k_state state;
 
+       struct work_struct register_work;
        struct work_struct restart_work;
 
        /* cycle count is reported twice for each visited channel during scan.