ath10k: suspend hardware before reset
authorMarek Puzyniak <marek.puzyniak@tieto.com>
Mon, 10 Feb 2014 16:14:24 +0000 (17:14 +0100)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 13 Feb 2014 15:24:17 +0000 (17:24 +0200)
In case of warm reset target need to be suspended.
Suspend function is extented to handle both cases
with disabling interrupts and without disabling interrupts.
Warm target reset requires suspend with all interrupts
disabled.

This patch depends on
ath10k: fix device initialization routine

Signed-off-by: Marek Puzyniak <marek.puzyniak@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
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h

index 0d161cf90608076b5eb669e30fcdadc235f9c573..ebc5fc2ede75cbac75da3a2f789a946d4e1274ad 100644 (file)
@@ -858,10 +858,34 @@ err:
 }
 EXPORT_SYMBOL(ath10k_core_start);
 
+int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt)
+{
+       int ret;
+
+       reinit_completion(&ar->target_suspend);
+
+       ret = ath10k_wmi_pdev_suspend_target(ar, suspend_opt);
+       if (ret) {
+               ath10k_warn("could not suspend target (%d)\n", ret);
+               return ret;
+       }
+
+       ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
+
+       if (ret == 0) {
+               ath10k_warn("suspend timed out - target pause event never came\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 void ath10k_core_stop(struct ath10k *ar)
 {
        lockdep_assert_held(&ar->conf_mutex);
 
+       /* try to suspend target */
+       ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
        ath10k_debug_stop(ar);
        ath10k_htc_stop(&ar->htc);
        ath10k_htt_detach(&ar->htt);
index 4f7ff9bd7813bea8c15e2b757b17b6c75bfe43d5..fae53f909550ae383ad44c127de1942c8703bfdf 100644 (file)
@@ -492,6 +492,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
 void ath10k_core_destroy(struct ath10k *ar);
 
 int ath10k_core_start(struct ath10k *ar);
+int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
 void ath10k_core_stop(struct ath10k *ar);
 int ath10k_core_register(struct ath10k *ar, u32 chip_id);
 void ath10k_core_unregister(struct ath10k *ar);
index 3d905932b5a296009ebd39d743857dbc419f1987..b2c65904449c31e52c0a8beefc5a8896630b46fd 100644 (file)
@@ -3442,22 +3442,14 @@ static int ath10k_suspend(struct ieee80211_hw *hw,
 
        mutex_lock(&ar->conf_mutex);
 
-       reinit_completion(&ar->target_suspend);
-
-       ret = ath10k_wmi_pdev_suspend_target(ar);
+       ret = ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND);
        if (ret) {
-               ath10k_warn("could not suspend target (%d)\n", ret);
+               if (ret == -ETIMEDOUT)
+                       goto resume;
                ret = 1;
                goto exit;
        }
 
-       ret = wait_for_completion_timeout(&ar->target_suspend, 1 * HZ);
-
-       if (ret == 0) {
-               ath10k_warn("suspend timed out - target pause event never came\n");
-               goto resume;
-       }
-
        ret = ath10k_hif_suspend(ar);
        if (ret) {
                ath10k_warn("could not suspend hif (%d)\n", ret);
index b3c5a1faad4390f5e64cfd7c7cda4a505256b9e7..91e501b5499ef0497b3bb8b22e718c691d00f315 100644 (file)
@@ -2443,7 +2443,7 @@ int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
                                   ar->wmi.cmd->pdev_set_channel_cmdid);
 }
 
-int ath10k_wmi_pdev_suspend_target(struct ath10k *ar)
+int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
 {
        struct wmi_pdev_suspend_cmd *cmd;
        struct sk_buff *skb;
@@ -2453,7 +2453,7 @@ int ath10k_wmi_pdev_suspend_target(struct ath10k *ar)
                return -ENOMEM;
 
        cmd = (struct wmi_pdev_suspend_cmd *)skb->data;
-       cmd->suspend_opt = WMI_PDEV_SUSPEND;
+       cmd->suspend_opt = __cpu_to_le32(suspend_opt);
 
        return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
 }
index 083079f3fdd41955164b388752126c058c95d701..fc1093a51ab13268170b7408887703770f9b381a 100644 (file)
@@ -4193,7 +4193,7 @@ int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
 int ath10k_wmi_connect_htc_service(struct ath10k *ar);
 int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
                                const struct wmi_channel_arg *);
-int ath10k_wmi_pdev_suspend_target(struct ath10k *ar);
+int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
 int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
 int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
                                  u16 rd5g, u16 ctl2g, u16 ctl5g);