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

Reply via email to