diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2013-07-16 09:38:57 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2013-07-30 18:01:19 +0300 |
commit | 818bdd16b229919cfd07447d261154a1343871e1 (patch) | |
tree | ceb7c266179a2add8a729ea6b56265c4d7e8891f /drivers/net/wireless/ath/ath10k/mac.c | |
parent | a96d7745592274077e517173ec2cdac2a22d5b79 (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.c | 56 |
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); |