We didn't wait for scan channel change event so we could end up sending frames to a different channel.
Signed-off-by: Michal Kazior <michal.kaz...@tieto.com> --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/core.h | 2 ++ drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 4 ++++ 4 files changed, 19 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 2be47f3..5ed04af 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -466,6 +466,7 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, init_completion(&ar->scan.started); init_completion(&ar->scan.completed); + init_completion(&ar->scan.on_channel); init_completion(&ar->install_key_done); init_completion(&ar->vdev_setup_done); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 1110551..6c681cf 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -303,11 +303,13 @@ struct ath10k { struct { struct completion started; struct completion completed; + struct completion on_channel; struct timer_list timeout; bool is_roc; bool in_progress; bool aborting; int vdev_id; + int roc_freq; } scan; struct { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index df57772..72ac899 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2294,10 +2294,12 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, INIT_COMPLETION(ar->scan.started); INIT_COMPLETION(ar->scan.completed); + INIT_COMPLETION(ar->scan.on_channel); ar->scan.in_progress = true; ar->scan.aborting = false; ar->scan.is_roc = true; ar->scan.vdev_id = arvif->vdev_id; + ar->scan.roc_freq = chan->center_freq; spin_unlock_bh(&ar->data_lock); memset(&arg, 0, sizeof(arg)); @@ -2318,8 +2320,18 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, spin_lock_bh(&ar->data_lock); ar->scan.in_progress = false; spin_unlock_bh(&ar->data_lock); + goto exit; + } + + ret = wait_for_completion_timeout(&ar->scan.on_channel, 3*HZ); + if (ret == 0) { + ath10k_warn("could not switch to channel for roc scan\n"); + ath10k_abort_scan(ar); + ret = -ETIMEDOUT; + goto exit; } + ret = 0; exit: mutex_unlock(&ar->conf_mutex); return ret; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index efa72fc..404976d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -202,6 +202,10 @@ static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) case WMI_SCAN_EVENT_FOREIGN_CHANNEL: ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_FOREIGN_CHANNEL\n"); ar->scan_channel = ieee80211_get_channel(ar->hw->wiphy, freq); + if (ar->scan.in_progress && ar->scan.is_roc && + ar->scan.roc_freq == freq) { + complete(&ar->scan.on_channel); + } break; case WMI_SCAN_EVENT_DEQUEUED: ath10k_dbg(ATH10K_DBG_WMI, "SCAN_EVENT_DEQUEUED\n"); -- 1.7.9.5 _______________________________________________ ath9k-devel mailing list ath9k-devel@lists.ath9k.org https://lists.ath9k.org/mailman/listinfo/ath9k-devel