aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-05-26 05:46:03 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-05-27 05:27:33 -0400
commitc5058f5b82f226b236dc5a65015152ed3c23efff (patch)
tree7ac9434df253e0dd7df885ccd07f8724afeea2b0 /drivers/net/wireless/ath
parentae254433a8dfaaf7983b39d87ce695a616d36163 (diff)
ath10k: perform hw restart lazily
This reduces risk of races and prepares for more hw restart fixes. It also makes sense to perform teardown after mac80211 starts its restart routine as it guarantees it has stopped itself by then (including tx queues). 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')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c34
2 files changed, 20 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 5980399029b4..82017f56e661 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -651,7 +651,8 @@ static void ath10k_core_restart(struct work_struct *work)
651 switch (ar->state) { 651 switch (ar->state) {
652 case ATH10K_STATE_ON: 652 case ATH10K_STATE_ON:
653 ar->state = ATH10K_STATE_RESTARTING; 653 ar->state = ATH10K_STATE_RESTARTING;
654 ath10k_halt(ar); 654 del_timer_sync(&ar->scan.timeout);
655 ath10k_reset_scan((unsigned long)ar);
655 ieee80211_restart_hw(ar->hw); 656 ieee80211_restart_hw(ar->hw);
656 break; 657 break;
657 case ATH10K_STATE_OFF: 658 case ATH10K_STATE_OFF:
@@ -660,6 +661,8 @@ static void ath10k_core_restart(struct work_struct *work)
660 ath10k_warn("cannot restart a device that hasn't been started\n"); 661 ath10k_warn("cannot restart a device that hasn't been started\n");
661 break; 662 break;
662 case ATH10K_STATE_RESTARTING: 663 case ATH10K_STATE_RESTARTING:
664 /* hw restart might be requested from multiple places */
665 break;
663 case ATH10K_STATE_RESTARTED: 666 case ATH10K_STATE_RESTARTED:
664 ar->state = ATH10K_STATE_WEDGED; 667 ar->state = ATH10K_STATE_WEDGED;
665 /* fall through */ 668 /* fall through */
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b98f88746f15..d73f146611b9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -2306,6 +2306,7 @@ void ath10k_halt(struct ath10k *ar)
2306 } 2306 }
2307 2307
2308 del_timer_sync(&ar->scan.timeout); 2308 del_timer_sync(&ar->scan.timeout);
2309 ath10k_reset_scan((unsigned long)ar);
2309 ath10k_offchan_tx_purge(ar); 2310 ath10k_offchan_tx_purge(ar);
2310 ath10k_mgmt_over_wmi_tx_purge(ar); 2311 ath10k_mgmt_over_wmi_tx_purge(ar);
2311 ath10k_peer_cleanup_all(ar); 2312 ath10k_peer_cleanup_all(ar);
@@ -2313,12 +2314,6 @@ void ath10k_halt(struct ath10k *ar)
2313 ath10k_hif_power_down(ar); 2314 ath10k_hif_power_down(ar);
2314 2315
2315 spin_lock_bh(&ar->data_lock); 2316 spin_lock_bh(&ar->data_lock);
2316 if (ar->scan.in_progress) {
2317 del_timer(&ar->scan.timeout);
2318 ar->scan.in_progress = false;
2319 ieee80211_scan_completed(ar->hw, true);
2320 }
2321
2322 list_for_each_entry(arvif, &ar->arvifs, list) { 2317 list_for_each_entry(arvif, &ar->arvifs, list) {
2323 if (!arvif->beacon) 2318 if (!arvif->beacon)
2324 continue; 2319 continue;
@@ -2401,8 +2396,18 @@ static int ath10k_start(struct ieee80211_hw *hw)
2401 2396
2402 mutex_lock(&ar->conf_mutex); 2397 mutex_lock(&ar->conf_mutex);
2403 2398
2404 if (ar->state != ATH10K_STATE_OFF && 2399 switch (ar->state) {
2405 ar->state != ATH10K_STATE_RESTARTING) { 2400 case ATH10K_STATE_OFF:
2401 ar->state = ATH10K_STATE_ON;
2402 break;
2403 case ATH10K_STATE_RESTARTING:
2404 ath10k_halt(ar);
2405 ar->state = ATH10K_STATE_RESTARTED;
2406 break;
2407 case ATH10K_STATE_ON:
2408 case ATH10K_STATE_RESTARTED:
2409 case ATH10K_STATE_WEDGED:
2410 WARN_ON(1);
2406 ret = -EINVAL; 2411 ret = -EINVAL;
2407 goto err; 2412 goto err;
2408 } 2413 }
@@ -2419,11 +2424,6 @@ static int ath10k_start(struct ieee80211_hw *hw)
2419 goto err_power_down; 2424 goto err_power_down;
2420 } 2425 }
2421 2426
2422 if (ar->state == ATH10K_STATE_OFF)
2423 ar->state = ATH10K_STATE_ON;
2424 else if (ar->state == ATH10K_STATE_RESTARTING)
2425 ar->state = ATH10K_STATE_RESTARTED;
2426
2427 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); 2427 ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1);
2428 if (ret) { 2428 if (ret) {
2429 ath10k_warn("failed to enable PMF QOS: %d\n", ret); 2429 ath10k_warn("failed to enable PMF QOS: %d\n", ret);
@@ -2482,12 +2482,10 @@ static void ath10k_stop(struct ieee80211_hw *hw)
2482 struct ath10k *ar = hw->priv; 2482 struct ath10k *ar = hw->priv;
2483 2483
2484 mutex_lock(&ar->conf_mutex); 2484 mutex_lock(&ar->conf_mutex);
2485 if (ar->state == ATH10K_STATE_ON || 2485 if (ar->state != ATH10K_STATE_OFF) {
2486 ar->state == ATH10K_STATE_RESTARTED ||
2487 ar->state == ATH10K_STATE_WEDGED)
2488 ath10k_halt(ar); 2486 ath10k_halt(ar);
2489 2487 ar->state = ATH10K_STATE_OFF;
2490 ar->state = ATH10K_STATE_OFF; 2488 }
2491 mutex_unlock(&ar->conf_mutex); 2489 mutex_unlock(&ar->conf_mutex);
2492 2490
2493 ath10k_mgmt_over_wmi_tx_purge(ar); 2491 ath10k_mgmt_over_wmi_tx_purge(ar);