summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/mac.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2013-07-16 09:38:57 +0200
committerKalle Valo <kvalo@qca.qualcomm.com>2013-07-30 18:01:19 +0300
commit818bdd16b229919cfd07447d261154a1343871e1 (patch)
treeceb7c266179a2add8a729ea6b56265c4d7e8891f /drivers/net/wireless/ath/ath10k/mac.c
parenta96d7745592274077e517173ec2cdac2a22d5b79 (diff)
ath10k: defer hw setup to start/stop mac80211 hooks
This fixes suspend-to-disk. The hardware is now re-initialized upon freeze/thaw properly. This also makes suspend/resume re-initialize the hardware as WoWLAN support is not done yet. With some little work it should be possible to support hw reconfiguration for hw/fw recovery. HW must be initialized once before registering to mac80211 because FW determinates what hw capabilities can be advertised. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/mac.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c56
1 files changed, 43 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b9663e94dba..2dfd446251b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1738,13 +1738,52 @@ static void ath10k_tx(struct ieee80211_hw *hw,
/*
* Initialize various parameters with default vaules.
*/
+static void ath10k_halt(struct ath10k *ar)
+{
+ lockdep_assert_held(&ar->conf_mutex);
+
+ del_timer_sync(&ar->scan.timeout);
+ ath10k_offchan_tx_purge(ar);
+ ath10k_peer_cleanup_all(ar);
+ ath10k_core_stop(ar);
+ ath10k_hif_power_down(ar);
+
+ spin_lock_bh(&ar->data_lock);
+ if (ar->scan.in_progress) {
+ del_timer(&ar->scan.timeout);
+ ar->scan.in_progress = false;
+ ieee80211_scan_completed(ar->hw, true);
+ }
+ spin_unlock_bh(&ar->data_lock);
+}
+
static int ath10k_start(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
- int ret;
+ int ret = 0;
mutex_lock(&ar->conf_mutex);
+ if (ar->state != ATH10K_STATE_OFF) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = ath10k_hif_power_up(ar);
+ if (ret) {
+ ath10k_err("could not init hif (%d)\n", ret);
+ ar->state = ATH10K_STATE_OFF;
+ goto exit;
+ }
+
+ ret = ath10k_core_start(ar);
+ if (ret) {
+ ath10k_err("could not init core (%d)\n", ret);
+ ath10k_hif_power_down(ar);
+ ar->state = ATH10K_STATE_OFF;
+ goto exit;
+ }
+
ret = ath10k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS, 1);
if (ret)
ath10k_warn("could not enable WMI_PDEV_PARAM_PMF_QOS (%d)\n",
@@ -1755,9 +1794,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
ath10k_warn("could not init WMI_PDEV_PARAM_DYNAMIC_BW (%d)\n",
ret);
- ar->state = ATH10K_STATE_ON;
ath10k_regd_update(ar);
+exit:
mutex_unlock(&ar->conf_mutex);
return 0;
}
@@ -1767,17 +1806,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex);
- del_timer_sync(&ar->scan.timeout);
- ath10k_offchan_tx_purge(ar);
- ath10k_peer_cleanup_all(ar);
-
- spin_lock_bh(&ar->data_lock);
- if (ar->scan.in_progress) {
- del_timer(&ar->scan.timeout);
- ar->scan.in_progress = false;
- ieee80211_scan_completed(ar->hw, true);
- }
- spin_unlock_bh(&ar->data_lock);
+ if (ar->state == ATH10K_STATE_ON)
+ ath10k_halt(ar);
ar->state = ATH10K_STATE_OFF;
mutex_unlock(&ar->conf_mutex);