Skip to content

Commit

Permalink
ath10k: perform hw restart lazily
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michal Kazior authored and Kalle Valo committed May 27, 2014
1 parent ae25443 commit c5058f5
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 19 deletions.
5 changes: 4 additions & 1 deletion drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,8 @@ static void ath10k_core_restart(struct work_struct *work)
switch (ar->state) {
case ATH10K_STATE_ON:
ar->state = ATH10K_STATE_RESTARTING;
ath10k_halt(ar);
del_timer_sync(&ar->scan.timeout);
ath10k_reset_scan((unsigned long)ar);
ieee80211_restart_hw(ar->hw);
break;
case ATH10K_STATE_OFF:
Expand All @@ -660,6 +661,8 @@ static void ath10k_core_restart(struct work_struct *work)
ath10k_warn("cannot restart a device that hasn't been started\n");
break;
case ATH10K_STATE_RESTARTING:
/* hw restart might be requested from multiple places */
break;
case ATH10K_STATE_RESTARTED:
ar->state = ATH10K_STATE_WEDGED;
/* fall through */
Expand Down
34 changes: 16 additions & 18 deletions drivers/net/wireless/ath/ath10k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -2306,19 +2306,14 @@ void ath10k_halt(struct ath10k *ar)
}

del_timer_sync(&ar->scan.timeout);
ath10k_reset_scan((unsigned long)ar);
ath10k_offchan_tx_purge(ar);
ath10k_mgmt_over_wmi_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);
}

list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->beacon)
continue;
Expand Down Expand Up @@ -2401,8 +2396,18 @@ static int ath10k_start(struct ieee80211_hw *hw)

mutex_lock(&ar->conf_mutex);

if (ar->state != ATH10K_STATE_OFF &&
ar->state != ATH10K_STATE_RESTARTING) {
switch (ar->state) {
case ATH10K_STATE_OFF:
ar->state = ATH10K_STATE_ON;
break;
case ATH10K_STATE_RESTARTING:
ath10k_halt(ar);
ar->state = ATH10K_STATE_RESTARTED;
break;
case ATH10K_STATE_ON:
case ATH10K_STATE_RESTARTED:
case ATH10K_STATE_WEDGED:
WARN_ON(1);
ret = -EINVAL;
goto err;
}
Expand All @@ -2419,11 +2424,6 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_power_down;
}

if (ar->state == ATH10K_STATE_OFF)
ar->state = ATH10K_STATE_ON;
else if (ar->state == ATH10K_STATE_RESTARTING)
ar->state = ATH10K_STATE_RESTARTED;

ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1);
if (ret) {
ath10k_warn("failed to enable PMF QOS: %d\n", ret);
Expand Down Expand Up @@ -2482,12 +2482,10 @@ static void ath10k_stop(struct ieee80211_hw *hw)
struct ath10k *ar = hw->priv;

mutex_lock(&ar->conf_mutex);
if (ar->state == ATH10K_STATE_ON ||
ar->state == ATH10K_STATE_RESTARTED ||
ar->state == ATH10K_STATE_WEDGED)
if (ar->state != ATH10K_STATE_OFF) {
ath10k_halt(ar);

ar->state = ATH10K_STATE_OFF;
ar->state = ATH10K_STATE_OFF;
}
mutex_unlock(&ar->conf_mutex);

ath10k_mgmt_over_wmi_tx_purge(ar);
Expand Down

0 comments on commit c5058f5

Please sign in to comment.