ath10k: retry warm reset a few times
authorMichal Kazior <michal.kazior@tieto.com>
Wed, 14 May 2014 13:56:16 +0000 (16:56 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 16 May 2014 13:48:37 +0000 (16:48 +0300)
Sometimes warm reset works upon retry. It might be
related to imperfect warm reset routine, but for
now let's just do the retries.

This should improve the reliability of some chips
that hang/crash with cold reset which is used as a
last resort if warm reset fails.

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

index 02dc4083882d1e5ea7c0c5b1fdaa720140e91a66..21a32ad4c09cbe97af1e8de2c7cd628570042028 100644 (file)
@@ -59,6 +59,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
 
 /* how long wait to wait for target to initialise, in ms */
 #define ATH10K_PCI_TARGET_WAIT 3000
+#define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
 
 #define QCA988X_2_0_DEVICE_ID  (0x003c)
 
@@ -2010,6 +2011,28 @@ err:
        return ret;
 }
 
+static int ath10k_pci_hif_power_up_warm(struct ath10k *ar)
+{
+       int i, ret;
+
+       /*
+        * Sometime warm reset succeeds after retries.
+        *
+        * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work
+        * at first try.
+        */
+       for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
+               ret = __ath10k_pci_hif_power_up(ar, false);
+               if (ret == 0)
+                       break;
+
+               ath10k_warn("failed to warm reset (attempt %d out of %d): %d\n",
+                           i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret);
+       }
+
+       return ret;
+}
+
 static int ath10k_pci_hif_power_up(struct ath10k *ar)
 {
        int ret;
@@ -2021,10 +2044,10 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
         * preferred (and safer) way to perform a device reset is through a
         * warm reset.
         *
-        * Warm reset doesn't always work though (notably after a firmware
-        * crash) so fall back to cold reset if necessary.
+        * Warm reset doesn't always work though so fall back to cold reset may
+        * be necessary.
         */
-       ret = __ath10k_pci_hif_power_up(ar, false);
+       ret = ath10k_pci_hif_power_up_warm(ar);
        if (ret) {
                ath10k_warn("failed to power up target using warm reset: %d\n",
                            ret);